diff --git a/.gitignore b/.gitignore index 069957d8a..66d38f2a9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +*.orig eressea.ini Debug Release @@ -36,3 +37,6 @@ game-e3/reports/ *.log.* tags Thumbs.db +.gdb_history +*.cfg +*.cmd diff --git a/.travis.yml b/.travis.yml index 18d2bfe81..de62c2200 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,5 +12,8 @@ addons: - libsqlite3-dev - libxml2-dev os: - - linux - - osx +- linux +- osx +notifications: + slack: + secure: F89aXLWaE125PaJIlETv12jT4EfH6wLXJmGCPZzrN3OcLn2ahDWqjwuzR7lOEDf2nAISmeMPyDZMhEHXLNHAE5qP6lg9yliYQw5hzGmDK9m1xUq/pPEne/b2Y7K3my1mkRZ6n3asbHgSmBWAfCIk1JN8R5Rv+rmbLuWLc+zofts= diff --git a/CMakeLists.txt b/CMakeLists.txt index 9730625b2..004248570 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,11 @@ project (eressea-server C) enable_testing() +find_package (LibXml2) +find_package (SQLite3) +find_package (Curses) +find_package (Lua REQUIRED) +find_package (ToLua REQUIRED) INCLUDE (CheckIncludeFiles) INCLUDE (CheckSymbolExists) @@ -30,6 +35,9 @@ CHECK_SYMBOL_EXISTS (sleep "unistd.h" HAVE_SLEEP) CHECK_SYMBOL_EXISTS (usleep "unistd.h" HAVE_USLEEP) CHECK_SYMBOL_EXISTS (access "unistd.h" HAVE_ACCESS) ENDIF(HAVE_UNISTD_H) +CHECK_SYMBOL_EXISTS (strlcpy "string.h" HAVE_STRLCPY) +CHECK_SYMBOL_EXISTS (strlcat "string.h" HAVE_STRLCAT) +CHECK_SYMBOL_EXISTS (slprintf "string.h" HAVE_SLPRINTF) CHECK_SYMBOL_EXISTS (strcasecmp "string.h" HAVE_STRCASECMP) CHECK_SYMBOL_EXISTS (strncasecmp "string.h" HAVE_STRNCASECMP) CHECK_SYMBOL_EXISTS (_strlwr "string.h" HAVE__STRLWR) @@ -54,13 +62,6 @@ CONFIGURE_FILE ( INCLUDE_DIRECTORIES (${CMAKE_BINARY_DIR}/include) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUSE_AUTOCONF") - -find_package (LibXml2) -find_package (SQLite3) -find_package (Curses) -find_package (Lua REQUIRED) -find_package (ToLua REQUIRED) - add_subdirectory (cutest) add_subdirectory (crypto) add_subdirectory (cJSON) @@ -70,5 +71,6 @@ add_subdirectory (quicklist) add_subdirectory (critbit) 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 share DESTINATION ${CMAKE_INSTALL_PREFIX}) diff --git a/README.md b/README.md index ce78fd36a..efd1318d9 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # What is this? -This repository contains an the source code for the Play-by-Mail strategy game [Eressea](http://www.eressea.de/). +This repository contains the source code for the Play-by-Mail strategy game [Eressea](http://www.eressea.de/). # Prerequisites diff --git a/autoconf.h.in b/autoconf.h.in index 5144d9ecc..1c151b6f9 100644 --- a/autoconf.h.in +++ b/autoconf.h.in @@ -26,6 +26,9 @@ #cmakedefine HAVE_MEMICMP 1 #cmakedefine HAVE__STRLWR 1 #cmakedefine HAVE_STRLWR 1 +#cmakedefine HAVE_STRLCPY 1 +#cmakedefine HAVE_STRLCAT 1 +#cmakedefine HAVE_SLPRINTF 1 #cmakedefine HAVE_SYS_STAT_MKDIR 1 #cmakedefine HAVE_DIRECT_MKDIR 1 #cmakedefine HAVE_DIRECT__MKDIR 1 diff --git a/conf/e2/config.xml b/conf/e2/config.xml index acd0d0677..b97abcea4 100644 --- a/conf/e2/config.xml +++ b/conf/e2/config.xml @@ -33,10 +33,17 @@ - - - - + + + + + + + + + + + @@ -89,11 +96,12 @@ - + + diff --git a/conf/e3/config.xml b/conf/e3/config.xml index 0e07e7fa3..31d9b31a7 100644 --- a/conf/e3/config.xml +++ b/conf/e3/config.xml @@ -32,7 +32,6 @@ - @@ -116,8 +115,11 @@ + + + diff --git a/conf/e4/config.xml b/conf/e4/config.xml index bdf4b4044..c8d6b21a3 100644 --- a/conf/e4/config.xml +++ b/conf/e4/config.xml @@ -32,7 +32,6 @@ - @@ -58,7 +57,6 @@ - @@ -119,6 +117,7 @@ + diff --git a/conf/eressea.ini b/conf/eressea.ini index a0d0b9fed..e14d0af50 100644 --- a/conf/eressea.ini +++ b/conf/eressea.ini @@ -12,7 +12,6 @@ locales = de,en install = . paths = lunit:scripts maxnmrs = 20 -rules = e2 [editor] color = 1 diff --git a/critbit b/critbit index 61989d933..e538739b3 160000 --- a/critbit +++ b/critbit @@ -1 +1 @@ -Subproject commit 61989d93368022602a2a7ac4218c83f254701f0f +Subproject commit e538739b38593b90312831a5e52d2e3bd731069b diff --git a/cutest b/cutest index 788659594..6e268687d 160000 --- a/cutest +++ b/cutest @@ -1 +1 @@ -Subproject commit 788659594ef87e9f497b8039da764182adfd2943 +Subproject commit 6e268687dbf6ae55afb63210c3753530d216a622 diff --git a/dlmalloc b/dlmalloc index 4292cd5e8..f1446c47c 160000 --- a/dlmalloc +++ b/dlmalloc @@ -1 +1 @@ -Subproject commit 4292cd5e81395d09a7457ab93659ea3b7784e958 +Subproject commit f1446c47ca1774ae84bf86a28502e91daf6b421a diff --git a/iniparser b/iniparser index 5b96eac07..ecf956b98 160000 --- a/iniparser +++ b/iniparser @@ -1 +1 @@ -Subproject commit 5b96eac07a88a215c616b0ae90d9ae6e3ed179b1 +Subproject commit ecf956b9808c28c2db52e6b73930f57876dbb258 diff --git a/process/cron/backup-eressea b/process/backup-eressea similarity index 100% rename from process/cron/backup-eressea rename to process/backup-eressea diff --git a/process/compress.py b/process/compress.py index 539f1a032..2ad62d814 100755 --- a/process/compress.py +++ b/process/compress.py @@ -38,9 +38,11 @@ for line in infile.readlines(): if not options.has_key("reports"): continue reports = options["reports"].split(",") -# reports = reports + [ "iso.cr" ] prefix = "%(turn)s-%(faction)s." % options files=[] + times="../parteien" + if os.path.isfile(times): + files = files + [ times ] if options["compression"]=="zip": output = prefix+"zip" files = [output] diff --git a/process/cron/create-orders b/process/create-orders similarity index 100% rename from process/cron/create-orders rename to process/create-orders diff --git a/process/cron/crontab b/process/cron/crontab new file mode 100644 index 000000000..8bbabab53 --- /dev/null +++ b/process/cron/crontab @@ -0,0 +1,18 @@ +# Crontab for Eressea on gruenbaer.kn-bremen.de + +PATH=/home/eressea/bin:/opt/bin:/usr/local/bin:/usr/bin:/bin +ERESSEA=/home/eressea/eressea +ATLANTIS=/home/eressea/atlantis +ENABLED=yes +PREVIEW=yes +CONFIRM=yes + +# m h dom mon dow command +00 00 * * * $HOME/bin/fetchmail.cron +00 22 * * * $HOME/bin/backup-db.sh + +15 21 * * Sat [ "$ENABLED" = "yes" ] && $ERESSEA/server/bin/run-eressea.cron 3 +25 21 * * Sat [ "$ENABLED" = "yes" ] && $ERESSEA/server/bin/run-eressea.cron 4 +35 21 * * Sat [ "$ENABLED" = "yes" ] && $ERESSEA/server/bin/run-eressea.cron 2 +39 08 * * Sun [ "$PREVIEW" = "yes" ] && $ERESSEA/server/bin/preview.cron +*/5 * * * * [ "$CONFIRM" = "yes" ] && $ERESSEA/server/bin/orders.cron 2 3 4 diff --git a/process/cron/orders.cron b/process/cron/orders.cron new file mode 100755 index 000000000..be573fe86 --- /dev/null +++ b/process/cron/orders.cron @@ -0,0 +1,16 @@ +#!/bin/bash + +## this script processes incoming order files. +# files are delivered into an incoming queue by procmail, then cron runs +# this here script to make a non-blocking syntax check and reject or +# accept the order file. + +for GAME in $* +do + if [ "$GAME" == "eressea" ]; then GAME=2 ; fi + if [ "$GAME" == "e3a" ]; then GAME=3 ; fi + if [ -e $HOME/eressea/game-$GAME/orders.queue ] + then + $HOME/bin/orders-process $GAME + fi +done diff --git a/s/cron/previews.sh b/process/cron/preview.cron similarity index 100% rename from s/cron/previews.sh rename to process/cron/preview.cron diff --git a/process/cron/run-eressea b/process/cron/run-eressea.cron similarity index 100% rename from process/cron/run-eressea rename to process/cron/run-eressea.cron index e932378fc..471031237 100755 --- a/process/cron/run-eressea +++ b/process/cron/run-eressea.cron @@ -40,6 +40,6 @@ fi echo "sending reports for game $GAME, turn $TURN" $BIN/compress.sh $GAME $TURN $BIN/sendreports.sh $GAME -$BIN/backup-eressea $GAME $TURN [ $GAME -lt 4 ] && $BIN/send-summary $GAME +$BIN/backup-eressea $GAME $TURN rm -f test/execute.lock diff --git a/process/cron/run-turn b/process/run-turn similarity index 100% rename from process/cron/run-turn rename to process/run-turn diff --git a/quicklist b/quicklist index 25ac9a7bf..45f4577b8 160000 --- a/quicklist +++ b/quicklist @@ -1 +1 @@ -Subproject commit 25ac9a7bf0d23f34cbf487edb0cb983eb842b90e +Subproject commit 45f4577b8205d87b78d2b1f30b5c9baa25c86779 diff --git a/res/adamantium.xml b/res/adamantium.xml index 315a8d66c..d5cdd4fae 100644 --- a/res/adamantium.xml +++ b/res/adamantium.xml @@ -1,4 +1,4 @@ - + diff --git a/res/armor.xml b/res/armor.xml index f24ddcd35..f26848da2 100644 --- a/res/armor.xml +++ b/res/armor.xml @@ -2,12 +2,12 @@ - - - - - - - + + + + + + + diff --git a/res/buildings.xml b/res/buildings.xml index 3d128a12c..02b86d227 100644 --- a/res/buildings.xml +++ b/res/buildings.xml @@ -1,4 +1,4 @@ - + diff --git a/res/core/common/items.xml b/res/core/common/items.xml index 9508653e7..c8910e695 100644 --- a/res/core/common/items.xml +++ b/res/core/common/items.xml @@ -2,7 +2,7 @@ - + diff --git a/res/core/de/strings.xml b/res/core/de/strings.xml index e2003f997..cd5dac609 100644 --- a/res/core/de/strings.xml +++ b/res/core/de/strings.xml @@ -1,10 +1,10 @@ Wirbel @@ -275,11 +275,6 @@ - - Tresen - counter - - wenige few @@ -731,7 +726,7 @@ an unknown building - ein unbekannter zauber + ein unbekannter Zauber an unknown spell @@ -746,6 +741,14 @@ einer unbekannten Einheit an unknown unit + + ein unbekannter Zauber + an unknown curse + + + Fehler: Unbekannter Schlüssel + Fehler: Unbekannter Schlüssel + @@ -2209,12 +2212,6 @@ Schaden - - - Deine Partei hat letzte Runde keinen Zug - abgegeben! - - Schneemann @@ -3569,13 +3566,13 @@ - + sehr stark - critically wounded + super strong - + stark - heavily wounded + strong schwer verwundet @@ -3655,11 +3652,11 @@ Erschaffe einen Ring der Macht - Create A Ring Of Power + Create A Ring of Power Schild des Fisches - Shield Of The Fish + Shield of the Fish Runen des Schutzes @@ -3667,7 +3664,7 @@ Ruf der Realität - Call Of Reality + Call of Reality Astraler Ruf @@ -3707,7 +3704,7 @@ Lied der Verführung - Song Of Seduction + Song of Seduction Aushorchen @@ -3715,11 +3712,11 @@ Kriegsgesang - Song Of War + Song of War Gesang der Angst - Song Of Fear + Song of Fear Lied des Ortes analysieren @@ -3735,7 +3732,7 @@ Erschaffe ein Amulett der Keuschheit - Create An Amulet Of Chastity + Create An Amulet of Chastity Beschleunigung @@ -3759,23 +3756,23 @@ Gesang des wachen Geistes - Song Of The Youthful Spirit + Song of the Youthful Spirit Gesang des schwachen Geistes - Song Of The Aging Spirit + Song of the Aging Spirit Gesang der Friedfertigkeit - Song Of Peace + Song of Peace Gesang der Versklavung - Song Of Slavery + Song of Slavery Hohe Kunst der Überzeugung - Song Of Slavery + Song of Slavery Zeitdehnung @@ -3823,7 +3820,7 @@ Erschaffe einen Ring der Regeneration - Create A Ring Of Regeneration + Create A Ring of Regeneration Mob aufwiegeln @@ -3859,7 +3856,7 @@ Erschaffe einen Beutel des Negativen Gewichts - Create A Bag Of Holding + Create A Bag of Holding Erschaffe einen Aurafocus @@ -3901,18 +3898,10 @@ Magie analysieren Analyze Magic - - Hohes Lied der Gaukelei - Song of Generosity - Gesang des Werbens Song of Courting - - Schleieraura - Veil - Lied der Heilung Blessed Harvest @@ -3933,7 +3922,7 @@ Gesang des Lebens analysieren Analyze Song of Life - + Bannlied Countersong @@ -3975,11 +3964,11 @@ Hainzauber - Grove Of Oak Trees + Grove of Oak Trees Rostregen - Rain Of Rust + Rain of Rust Firuns Fell @@ -4011,7 +4000,7 @@ Wurzeln der Magie - Roots Of Magic + Roots of Magic Mahlstrom @@ -4057,12 +4046,12 @@ Erschaffe ein Amulett des wahren Sehens - Create An Amulet Of True Sight + Create An Amulet of True Sight Erschaffe einen Ring der Unsichtbarkeit - Create A Ring Of Invisibility + Create A Ring of Invisibility Miriams flinke Finger @@ -4078,7 +4067,7 @@ Blick des Basilisken - Gaze Of The Basilisk + Gaze of the Basilisk Starkes Tor und feste Mauer @@ -4098,11 +4087,11 @@ Weg der Bäume - Path Of Trees + Path of Trees Sog des Lebens - Ties Of Life + Ties of Life Heiliger Boden @@ -4115,7 +4104,7 @@ Erwecke Ents - Awakening Of The Ents + Awakening of the Ents Segne Steinkreis @@ -4159,7 +4148,7 @@ Rosthauch - Winds Of Rust + Winds of Rust Machtübertragung @@ -4167,11 +4156,11 @@ Feuerwand - Wall Of Fire + Wall of Fire Fluch der Pestilenz - Curse Of Pestilence + Curse of Pestilence Wahnsinn des Krieges @@ -4192,7 +4181,7 @@ Erschaffe einen Gürtel der Trollstärke - Create A Belt Of Troll + Create A Belt of Troll Strength @@ -4261,11 +4250,11 @@ Traumschlößchen - Castle Of Illusion + Castle of Illusion Traum der Magie - Dream Of Magic + Dream of Magic Gestaltwandlung @@ -4335,7 +4324,7 @@ Kraft der Natur force of nature - + Gesang der Götter Song of the Gods @@ -4343,8 +4332,160 @@ Göttliche Macht Power of the Gods + + Runen des Schutzes + Protective Runes + + + Störe Astrale Integrität + Astral Disruption + + + Gabe des Chaos + Chaos Gift + + + Schlechter Schlaf + Insomnia + + + Gesang des schwachen Geistes + Song of the Aging Spirit + + + Monster friedlich stimmen + Calm Monster + + + Gesang der Melancholie + Song of Melancholy + + + Beschwörung eines Hitzeelementar + Summon Fire Elemental + + + ein unbekannter Zauber + an unknown spell + + + Luftschiff + Airship + + + ein unbekannter Zauber + an unknown spell + + + Chaosfluch + Chaos Curse + + + Schöne Träume oder Schlechte Träume + Good Dreams or Bad Dreams + + + Hohes Lied der Gaukelei + Song of Generosity + + + Fluch der Götter + Curse of the Gods + + + Gesang des wachen Geistes + Song of the Youthful Spirit + + + Firuns Fell + Firun's Coat + + + Schleieraura + Concealing Aura + + + Magieresistenz + Magic Resistance + + + Heimstein + Homestone + + + Mauern der Ewigkeit + Eternal Walls + + + Wasserelementar + Water Elemental + + + Unbekannter Effekt + Unknown Effect + + + Unbekannter Effekt + Unknown Effect + + + Gesang der Friedfertigkeit + Song of Peace + + + Aufruhr + Riot + + + Unbekannter Effekt + Unknown Effect + + + Gesang der Versklavung + Song of Slavery + + + Unbekannter Effekt + Unknown Effect + + + Zeitdehnung + Double Time + + + Sturmelementar + Storm Elemental + + + Unbekannter Effekt + Unknown Effect + + + Alp + Nightmare + + + Feuerwand + Firewall + + + Zone der Heilung + Zone of Healing + + + Beschleunigung + Acceleration + + + Erzeugt einen Ring der Regeneration. + Creates a ring of regeneration. + + + Erzeugt einen Aurafokus. + Creates an aurafocus crystal. + Tötet die Feinde mit Säure. Kills enemies with acid. @@ -4414,7 +4555,7 @@ - Mit Hilfe dieses Zauber kann der Magier eigene Aura im Verhältnis + Mit Hilfe dieses Zaubers kann der Magier eigene Aura im Verhältnis 2:1 auf einen anderen Magier des gleichen Magiegebietes oder im Verhältnis 3:1 auf einen Magier eines anderen Magiegebietes übertragen. @@ -4478,7 +4619,7 @@ Dieses magische Lied wird, einmal mit Inbrunst gesungen, sich in der Region fortpflanzen, von Mund zu Mund springen und eine Zeitlang überall zu vernehmen sein. Nach wie vielen Wochen der Gesang aus dem - Gedächnis der Region entschwunden ist, ist von dem Geschick des Barden + Gedächtnis der Region entschwunden ist, ist von dem Geschick des Barden abhängig. Bis das Lied ganz verklungen ist, wird seine Magie allen Verbündeten des Barden (HELFE BEWACHE), und natürlich auch seinen eigenem Volk, einen einmaligen Bonus von 15% @@ -4985,10 +5126,10 @@ able to decipher all enchantments or spells, which aren't disguised beyond your capability. - + Dieser schrille Gesang hallt über das ganze Schlachtfeld. Die besonderen Dissonanzen in den - Melodien machen es Magier fast unmöglich, sich auf ihre + Melodien machen es Magiern fast unmöglich, sich auf ihre Zauber zu konzentrieren. The screeching sounds of this melody can be heard across the whole battlefield. Wizards @@ -5001,7 +5142,7 @@ kann, was für Gegenstände sie mit sich führt und sollte sie magisch begabt sein, sogar welche Zauber sie beherrscht. Leider beeinflußt dieser Zauber nicht das - Gedächnis, und so wird sie sich im nachhinein wohl + Gedächtnis, und so wird sie sich im nachhinein wohl bewußt werden, dass sie zuviel erzählt hat. The persons of the bewitched unit starts to babble without control about what it is said, @@ -5026,7 +5167,7 @@ STRASSE, so werden pro Golem 4 Steine verbaut und der Golem löst sich auf. 'Take a flawless block of crystaline - stone and humidify it with a vial of Water Of Life until + stone and humidify it with a vial of Water of Life until the potion has been soaked up completely. Then focus your power on the forming aura of life and shape a container for the unbound forces'. The more power a magician @@ -5077,7 +5218,7 @@ armor will get rusty. The exact number of items affected by the rain depends on the ammount of power invested by the magician. Up to ten - weapons can be destroyed per level - a Ring Of + weapons can be destroyed per level - a Ring of Power increases the effect like an additional level. @@ -5094,7 +5235,7 @@ cold of a glacier. Under the effect of this spell, insects are able to enter glaciers and act normally there. Ten insects per level can be - protected in this way. A Ring Of Power increases + protected in this way. A Ring of Power increases the number by additional ten. @@ -5103,7 +5244,7 @@ sich. Sodann kann er ihnen befehlen, den Gegner mit Hagelkörnern und Eisbrocken zuzusetzen. During a battle the druid calls the - Elemental Spirits Of Cold and binds them to + Elemental Spirits of Cold and binds them to himself. Then he commands them to attack his foes with hail and ice missiles. @@ -5148,7 +5289,7 @@ Windes beschwört plötzliche Windböen, kleine Windhosen und Luftlöcher herauf, die die gegnerischen Schützen behindern werden. - Calling the Elemental Spirits Of Wind + Calling the Elemental Spirits of Wind conjurs up sudden breezes, small whirlwinds and minor turbulences that will hinder enemy archers. @@ -5171,7 +5312,7 @@ Winde oder Strömungen beeinträchtigt. While being aboard a ship, the druid uses this ritual to force the Elemental Spirits - Of Water to serve him and commands them to carry + of Water to serve him and commands them to carry the ship across the water at a higher speed. In addition, the ship will not be affected by unfavourable winds or currents. @@ -5187,7 +5328,7 @@ who can help those who got injured during a battle. Druids are, with the help of a summons of - the Elemental Spirits Of Life, able to heal + the Elemental Spirits of Life, able to heal wounds, mend broken bones or even regenerate separated limbs as well. @@ -5198,7 +5339,7 @@ starke Winde oder gar Stürme und behindern alle Schützen einer Schlacht. This summons opens a gate to the plane - of Elemental Spirits Of Wind. Immediately, + of Elemental Spirits of Wind. Immediately, strong winds or even storms will rise near the gate and hinder all archers during a battle. @@ -5209,7 +5350,7 @@ das Zaubern für die Dauer des Kampfes deutlich schwerer fallen. This ritual summons some Elemental - Spirits Of Magic and sends them into the ranks + Spirits of Magic and sends them into the ranks of the enemy mages. Casting spells will be much harder for them during the battle. @@ -5229,7 +5370,7 @@ Erdbeben wird alle Gebäude in der Region beschädigen. With this ritual the druid summons an - Elemental Spirit Of Earth that brings the ground + Elemental Spirit of Earth that brings the ground to shake. This earthquake damages all buildings in the target region. @@ -5243,7 +5384,7 @@ desto größer ist die Zahl der Elementargeister, die sich bannen lassen. Für jedes Schiff wird ein Elementargeist benötigt. - Calling the Elemental Spirits Of Storm + Calling the Elemental Spirits of Storm is an ancient ritual. The druid binds the elementals to a ship's sails where they can help to carry the vessel across the waves at an @@ -5297,7 +5438,7 @@ die sich mit ihrem Tarnungs-Talent verstecken, bleiben weiterhin unentdeckt. This spell enables the caster to - create an Amulet Of True Sight. Wearing such an + create an Amulet of True Sight. Wearing such an amulet, a person can discover anyone wearing a Ring of Invisibility. Anyway, units concealed by the use of their stealth skill will remain @@ -5339,11 +5480,11 @@ Wahrnehmung auch sein mag. In einer unsichtbaren Einheit muss jede Person einen Ring tragen. With this spell the caster can create - a Ring Of Invisibility. The wearer of this ring + a Ring of Invisibility. The wearer of this ring will be invisible to all units of other factions, no matter how good their perception skill may be. In an invisible unit, each person - must wear a Ring Of Invisibility. + must wear a Ring of Invisibility. Mit dieser Formel bindet der Magier @@ -5383,7 +5524,7 @@ betroffenen Personen werden nicht mehr kämpfen, können jedoch auch nicht verwundet werden. This complicated but effective spell - uses the Elemental Spirits Of Stone to turn a + uses the Elemental Spirits of Stone to turn a number of enemies to stone for the duration of combat. The affected persons won't be able to fight any more, but they can't be wounded @@ -5397,7 +5538,7 @@ besseren Schutz gegen Angriffe mit dem Schwert wie mit Magie. At the beginning of a battle, the - magician binds some Elemental Spirits Of Rock to + magician binds some Elemental Spirits of Rock to the walls of the builing in which he currently is. The structure will then provide a better protection against attacks by sword or by magic. @@ -5430,7 +5571,7 @@ A great power lies within those places that are pulsing with life. A druid can focus this power and thereby create a gate into the - World Of Spirits. He can then send level*5 + World of Spirits. He can then send level*5 weight units of living or dead matter through the gate. @@ -5440,7 +5581,7 @@ Zaubers Stufe*5 Gewichtseinheiten in einen Wald auf der materiellen Welt zurückschicken. A druid who has traveled to the World - Of Spirits can use this spell to send level*5 + of Spirits can use this spell to send level*5 weight units of living or dead matter back to a forest in the material world. @@ -5543,7 +5684,7 @@ und so wird die Phase der Macht abgelöst von einer Phase der Schwäche. The sorcerer opens his mind to the - Spheres Of Chaos so that he can access a greater + Spheres of Chaos so that he can access a greater ammount of magical power for a while. But the help of the Chaos Lords has its price - and so the period of power will be followed by a period @@ -5673,7 +5814,7 @@ Sie sind schwer zu treffen und entziehen ihrem Gegner Kraft. With the help of dark rituals the - sorcerer summons demons from the Sphere Of + sorcerer summons demons from the Sphere of Shadows. These fearsome creatures can walk almost unseen among the living, but their dark aura can be sensed by everyone. Shadow demons @@ -5767,7 +5908,7 @@ Darkness are at their peak, the sorcerer can use his powers to destroy enchantments. In order to do so, he draws a pentagram on a surface of the - enchanted object and begins calling the Lords Of + enchanted object and begins calling the Lords of Darkness. The Lords will aid him, but whether he is able to undo the target spell or not depends upon his own power. @@ -5798,7 +5939,7 @@ Schaden zufügen. By performing a gruesome ritual and sacrificing his own blood the Sorcerer conjurs - up a spirit from the Elemental Plane Of Poison. + up a spirit from the Elemental Plane of Poison. It will take the form of a green cloud of toxic gases that envelops a whole region and that will harm anyone within. @@ -5817,7 +5958,7 @@ irresistable scent to dragons. It is not known whether the dragons come from surrounding regions or if they have their origin in the - Sphere Of Chaos. The bait will exist for about + Sphere of Chaos. The bait will exist for about six weeks, but it must be placed in a tarrain that is suitable for dragons. @@ -5831,7 +5972,7 @@ Sie sind schwer zu treffen und entziehen ihrem Gegner Kraft und Leben. With the help of dark rituals the - sorcerer summons demons from the Sphere Of + sorcerer summons demons from the Sphere of Shadows. These fearsome creatures can walk almost unseen among the living, but their dark aura can be sensed by everyone. Shadowmasters @@ -5848,7 +5989,7 @@ seiner Macht zu beseelen...' 'So take the blood of a fierce warrior and apply it to the steel of the blade. Then - start calling the Spheres Of Chaos. If you did + start calling the Spheres of Chaos. If you did everything to their pleasure, they will send a minor one of their kind to fulfill the sword with his power.' diff --git a/res/core/en/strings.xml b/res/core/en/strings.xml index e68915f06..d80c742b9 100644 --- a/res/core/en/strings.xml +++ b/res/core/en/strings.xml @@ -1660,10 +1660,6 @@ - - No orders were received for your faction! - - Mistelzweig diff --git a/res/core/fr/strings.xml b/res/core/fr/strings.xml index 312078f7a..8acc1d89f 100644 --- a/res/core/fr/strings.xml +++ b/res/core/fr/strings.xml @@ -1,4 +1,4 @@ - + @@ -121,7 +121,7 @@ couloir - dsert + désert mur de feu @@ -130,7 +130,7 @@ brume - fort + foręt glacier @@ -148,13 +148,13 @@ iceberg - maelstrm + maelström montagne - ocan + océan plaine @@ -169,7 +169,7 @@ volcan - tempte magique + tempęte magique @@ -179,7 +179,7 @@ un %s - le dsert de %s + le désert de %s un %s @@ -188,7 +188,7 @@ fog_trail %s - la fort de %s + la foręt de %s le glacier de %s @@ -277,11 +277,11 @@ - une unit inconnue + une unité inconnue - Messages et Evnements + Messages et Evénements Avertissements et Erreurs @@ -296,7 +296,7 @@ Magie et Reliques - Dplacements et Voyages + Déplacements et Voyages Apprentissage et Enseignement @@ -313,25 +313,25 @@ - universit + université - cromlech sacr + cromlech sacré - caravansrail + caravansérail barrage - btiment + bâtiment port - chteau illusoire + château illusoire auberge @@ -349,7 +349,7 @@ monument - carrire + carričre scierie @@ -358,7 +358,7 @@ forge - curie + écurie cromlech @@ -381,7 +381,7 @@ tour - chteau + château place-forte @@ -403,10 +403,10 @@ - cu + écu - cus + écus point de vie @@ -453,10 +453,10 @@ cristaux antimagie - amulette de chastet + amulette de chasteté - amulettes de chastet + amulettes de chasteté amulette du chaton @@ -465,10 +465,10 @@ amulettes du chaton - amulette de tnbres + amulette de ténčbres - amulettes de tnbres + amulettes de ténčbres amulette de rassemblement @@ -483,10 +483,10 @@ amulettes de soin - amulette de vrit + amulette de vérité - amulettes de vrit + amulettes de vérité pomme @@ -531,16 +531,16 @@ cottes de mailles - gteau + gâteau - gteaux + gâteaux - arbalte + arbalčte - arbaltes + arbalčtes dauphin @@ -555,13 +555,13 @@ sang de dragon - tte de dragon + tęte de dragon - ttes de dragons + tętes de dragons - trsor de dragon + trésor de dragon oniroeil @@ -588,10 +588,10 @@ bottes elfiques - pe ardente + épée ardente - pes ardentes + épées ardentes grand arc @@ -654,10 +654,10 @@ boucliers en laen - pe en laen + épée en laen - pes en laen + épées en laen lance @@ -666,10 +666,10 @@ lances - stre + stčre - stres + stčres sac magique @@ -696,10 +696,10 @@ arcs en mallorn - arbalte en mallorn + arbalčte en mallorn - arbaltes en mallorn + arbalčtes en mallorn lance en mallorn @@ -708,10 +708,10 @@ lances en mallorn - pieu en mallorn + épieu en mallorn - pieux en mallorn + épieux en mallorn bourse @@ -738,10 +738,10 @@ noix - pgase + pégase - pgases + pégases homme @@ -762,10 +762,10 @@ cartes de presse - anneau d'invisibilit + anneau d'invisibilité - anneaux d'invisibilit + anneaux d'invisibilité anneau de pouvoir @@ -774,46 +774,46 @@ anneaux de pouvoir - anneau de dextrit + anneau de dextérité - anneaux de dextrit + anneaux de dextérité - anneau de rgnration + anneau de régénération - anneaux de rgnration + anneaux de régénération - pe runique + épée runique - pes runiques + épées runiques - cotte de mailles rouille + cotte de mailles rouillée - cottes de mailles rouilles + cottes de mailles rouillées - bouclier rouill + bouclier rouillé - boucliers rouills + boucliers rouillés - pe rouille + épée rouillée - pes rouilles + épées rouillées - tte de serpent de mer + tęte de serpent de mer - ttes de serpents de mer + tętes de serpents de mer bouclier @@ -828,10 +828,10 @@ sacs de contenance - pieu + épieu - pieux + épieux pierre @@ -840,10 +840,10 @@ pierres - pe + épée - pes + épées pot de bave de crapaud @@ -858,16 +858,16 @@ ceintures de trolls - unit + unité - units + unités - potion de comptences + potion de compétences - potions de comptences + potions de compétences cristal astral @@ -894,10 +894,10 @@ feux d'artifice - coeur de pain d'pices + coeur de pain d'épices - coeurs de pain d'pices + coeurs de pain d'épices @@ -905,7 +905,7 @@ baume - pices + épices joyau @@ -929,7 +929,7 @@ baume - pices + épices myrrhe @@ -946,10 +946,10 @@ - Ceinture des Lgendes + Ceinture des Légendes - Ceintures des Lgendes + Ceintures des Légendes @@ -960,10 +960,10 @@ astragales - mritoine + méritoine - mritoines + méritoines oeil de hibou @@ -972,10 +972,10 @@ yeux de hibou - soie d'araigne + soie d'araignée - soies d'araigne + soies d'araignée obbadion @@ -1026,16 +1026,16 @@ fleurs de souffre - feuille de Tsha + feuille de Tshaď - feuilles de Tsha + feuilles de Tshaď - blidane + bélidane - blidanes + bélidanes racine de mandragore @@ -1062,16 +1062,16 @@ boralmes - ficode cristaux + ficoďde ŕ cristaux - ficodes cristaux + ficoďdes ŕ cristaux - blmissure + blémissure - blmissures + blémissures rose des neiges @@ -1080,10 +1080,10 @@ roses des neiges - th de sept lieues + thé de sept lieues - th de sept lieues + thé de sept lieues breuvage de Goliath @@ -1092,16 +1092,16 @@ breuvage de Goliath - lixir de vie + élixir de vie - lixir de vie + élixir de vie - vin du travail acharn + vin du travail acharné - vin du travail acharn + vin du travail acharné onguent de soin @@ -1134,10 +1134,10 @@ extraits de canicule - fourrage de l'talon + fourrage de l'étalon - fourrage de l'talon + fourrage de l'étalon vin de folie @@ -1183,7 +1183,7 @@ AURA - + ARBRES @@ -1213,10 +1213,10 @@ ETRANGER - + BATIMENT - + OBJETS @@ -1234,16 +1234,16 @@ CONTROLE - + PLANTES - + COMBAT NON - + SUIVANT @@ -1270,16 +1270,16 @@ ECUS - + ROUTES NIVEAU - + TEMPORAIRE - + POTIONS @@ -1303,7 +1303,7 @@ arc - maon + maçon charron @@ -1312,7 +1312,7 @@ catapulte - arbalte + arbalčte divertissement @@ -1330,7 +1330,7 @@ magie - mle + męlée mineur @@ -1345,7 +1345,7 @@ perrayeur - quitation + équitation cantonnier @@ -1360,7 +1360,7 @@ endurance - discrtion + discrétion tactique @@ -1625,10 +1625,10 @@ troll - dmons + démons - dmons + démons insectes @@ -1703,10 +1703,10 @@ draconien - spciaux + spéciaux - spcial + spécial enchantements @@ -1733,16 +1733,16 @@ ombre - lmures + lémures - lmure + lémure - ytis + yétis - yti + yéti quauquemaires @@ -1757,10 +1757,10 @@ crapaud - cphalophages + céphalophages - cphalophage + céphalophage paysans @@ -1805,16 +1805,16 @@ loup - fantmes + fantômes - fantme + fantôme - chats des rves + chats des ręves - chat des rves + chat des ręves chats de l'Enfer @@ -1835,10 +1835,10 @@ dauphin - tortues gantes + tortues géantes - tortue gante + tortue géante krakens @@ -1883,10 +1883,10 @@ hibou - fes + fées - fe + fée aigles @@ -1937,10 +1937,10 @@ spectre - fantmes du muse + fantômes du musée - fantme du muse + fantôme du musée gnomes @@ -1949,16 +1949,16 @@ gnome - modles + modčles - modle + modčle - mtamorphes + métamorphes - mtamorphe + métamorphe @@ -1973,20 +1973,20 @@ Statut Politique - Plantes ncessaires + Plantes nécessaires en construction - de dgts + de dégâts - Votre faction a t limine. Nous esprons que vous vous tes bien amus malgr tout, et vous encourageons vous rincrire pour une nouvelle partie. + Votre faction a été éliminée. Nous espérons que vous vous ętes bien amusé malgré tout, et vous encourageons ŕ vous réincrire pour une nouvelle partie. - comptences + compétences possessions @@ -2013,13 +2013,13 @@ attaque - dfense + défense armure - dgts + dégâts @@ -2030,28 +2030,25 @@ baguettes - + - cte nord-ouest + côte nord-ouest - cte nord-est + côte nord-est - cte est + côte est - cte sud-est + côte sud-est - cte sud-ouest + côte sud-ouest - cte ouest + côte ouest - - Aucun ordre reu pour votre faction ! - diff --git a/res/core/messages.xml b/res/core/messages.xml index c8eba5cfb..237ab8c7a 100644 --- a/res/core/messages.xml +++ b/res/core/messages.xml @@ -1,4 +1,4 @@ - + @@ -29,7 +29,7 @@ - "Einheiten knnen die folgenden Gegenstnde beanspruchen: $resources($items)" + "Einheiten können die folgenden Gegenstände beanspruchen: $resources($items)" "Units can claim the following items: $resources($items)" @@ -44,9 +44,8 @@ - - "$unit($mage) lt einen Teil seiner selbst in die Erde fliessen. Die Bume, die Transformation berlebt haben, erscheinen nun viel krftiger." + "$unit($mage) läßt einen Teil seiner selbst in die Erde fliessen. Die Bäume, die Transformation überlebt haben, erscheinen nun viel kräftiger." "The power of $unit($mage) flows into the ground and the trees which survived the spell appear much stronger now." @@ -54,14 +53,14 @@ - "$unit($mage) beschwrt einen Luftgeist, der die $ship($ship) in die Wolken hebt." + "$unit($mage) beschwört einen Luftgeist, der die $ship($ship) in die Wolken hebt." "$unit($mage) summons a wind spirit that lifts the $ship($ship) into the clouds." - "$unit($mage) beschwrt einen Schleier der Verwirrung." + "$unit($mage) beschwört einen Schleier der Verwirrung." "$unit($mage) summons a fog of confusion." @@ -78,7 +77,7 @@ - Dieser mchtige Bann scheint die Einheit ihres freien Willens zu berauben. Solange der Zauber wirkt, wird sie nur den Befehlen ihres neuen Herrn gehorchen. ($int36($id)) + Dieser mächtige Bann scheint die Einheit ihres freien Willens zu berauben. Solange der Zauber wirkt, wird sie nur den Befehlen ihres neuen Herrn gehorchen. ($int36($id)) This powerful curse appears to rob the unit of its free will. As long as the curse is active, it will only obey the orders of its new lord. ($int36($id)) @@ -88,7 +87,7 @@ - Dieser Zauber verursacht einen gigantischen magischen Strudel. Der Mahlstrom wird alle Schiffe, die in seinen Sog geraten, schwer beschdigen. ($int36($id)) + Dieser Zauber verursacht einen gigantischen magischen Strudel. Der Mahlstrom wird alle Schiffe, die in seinen Sog geraten, schwer beschädigen. ($int36($id)) This spell causes a gargantuan vortex. The maelstrom will heavily damage all ships coming into its wake. ($int36($id)) @@ -115,7 +114,7 @@ - "$unit($unit) wird von bsen Alptrumen geplagt. ($int36($id))" + "$unit($unit) wird von bösen Alpträumen geplagt. ($int36($id))" "$unit($unit) is haunted by terrbile nightmares. ($int36($id))" @@ -139,7 +138,7 @@ - "Eine Melodie erklingt, und $unit($unit) tanzt bis spt in die Nacht hinein. ($int36($id))" + "Eine Melodie erklingt, und $unit($unit) tanzt bis spät in die Nacht hinein. ($int36($id))" "A haunting melody fills the air, and $unit($unit) dances until late into the night. ($int36($id))" @@ -147,7 +146,7 @@ - "$unit($unit) findet eine kleine Flte, die eine wundersame Melodie spielt. ($int36($id))" + "$unit($unit) findet eine kleine Flöte, die eine wundersame Melodie spielt. ($int36($id))" "$unit($unit) finds a small flute that plays a beautiful melody. ($int36($id))" @@ -179,14 +178,14 @@ "A spell is deflecting magical energies and weakening all other spells cast in the region. ($int36($id))" - "Dieser Zauber scheint magische Energien irgendwie abzuleiten und so alle in der Region gezauberten Sprche in ihrer Wirkung zu schwchen oder ganz zu verhindern. ($int36($id))" + "Dieser Zauber scheint magische Energien irgendwie abzuleiten und so alle in der Region gezauberten Sprüche in ihrer Wirkung zu schwächen oder ganz zu verhindern. ($int36($id))" - "Ein Einhorn berhrt $unit($unit) mit seinem Horn und verschwindet kurz darauf im Unterholz. ($int36($id))" + "Ein Einhorn berührt $unit($unit) mit seinem Horn und verschwindet kurz darauf im Unterholz. ($int36($id))" "A unicorn touches $unit($unit) with its horn and vanishes into the forest quickly after. ($int36($id))" @@ -202,7 +201,7 @@ - "Leuchtende Blumen erblhen rund um das Lager von $unit($unit). ($int36($id))" + "Leuchtende Blumen erblühen rund um das Lager von $unit($unit). ($int36($id))" "Brightly coloured flowers pop up all around $unit($unit)'s camp. ($int36($id))" @@ -210,7 +209,7 @@ - "ber $unit($unit) zieht eine Gruppe Geier ihre Kreise. ($int36($id))" + "Über $unit($unit) zieht eine Gruppe Geier ihre Kreise. ($int36($id))" "A group of vultures circles above $unit($unit). ($int36($id))" @@ -218,7 +217,7 @@ - "Der Kopf von $unit($unit) hat sich in einen grinsenden Totenschdel verwandelt. ($int36($id))" + "Der Kopf von $unit($unit) hat sich in einen grinsenden Totenschädel verwandelt. ($int36($id))" "The head of $unit($unit) has turned into a madly grinning skull. ($int36($id))" @@ -234,7 +233,7 @@ - "Pestbeulen befallen den Krper von $unit($unit). ($int36($id))" + "Pestbeulen befallen den Körper von $unit($unit). ($int36($id))" "The body of $unit($unit) is disfigured by hideous boils. ($int36($id))" @@ -242,7 +241,7 @@ - "Eine dunkle Fee erscheint $unit($unit) im Schlaf. Sie ist von schauriger Schnheit. ($int36($id))" + "Eine dunkle Fee erscheint $unit($unit) im Schlaf. Sie ist von schauriger Schönheit. ($int36($id))" "A dark and mysterious fairy appears before $unit($unit). She is of bewitching beauty. ($int36($id))" @@ -250,7 +249,7 @@ - "Fulnisgeruch dringt $unit($unit) aus allen Krperffnungen. ($int36($id))" + "Fäulnisgeruch dringt $unit($unit) aus allen Körperöffnungen. ($int36($id))" "The stench of decay is poring from all the orifices of $unit($unit). ($int36($id))" @@ -259,7 +258,7 @@ - "$unit($unit) scheint $faction($faction) zu mgen. ($int36($id))" + "$unit($unit) scheint $faction($faction) zu mögen. ($int36($id))" "$unit($unit) likes $faction($faction). ($int36($id))" @@ -268,7 +267,7 @@ - "$unit($unit) scheint $race($race, 0) zu mgen. ($int36($id))" + "$unit($unit) scheint $race($race, 0) zu mögen. ($int36($id))" "$unit($unit) seems to like $race($race, 0). ($int36($id))" @@ -277,7 +276,7 @@ - "$unit($unit) ist ungewhnlich ungeschickt in $skill($skill). ($int36($id))" + "$unit($unit) ist ungewöhnlich ungeschickt in $skill($skill). ($int36($id))" "$unit($unit) has some troubles with $skill($skill). ($int36($id))" @@ -286,7 +285,7 @@ - "$unit($unit) ist ungewhnlich geschickt in $skill($skill). ($int36($id))" + "$unit($unit) ist ungewöhnlich geschickt in $skill($skill). ($int36($id))" "$unit($unit) is incredibly skilled at $skill($skill). ($int36($id))" @@ -314,7 +313,7 @@ - "$int($number) $if($eq($number,1), "Person", "Personen") von $unit($unit) $if($eq($number,1), "fhlt", "fhlen") sich vor Klte geschtzt. ($int36($id))" + "$int($number) $if($eq($number,1), "Person", "Personen") von $unit($unit) $if($eq($number,1), "fühlt", "fühlen") sich vor Kälte geschützt. ($int36($id))" "$int($number) $if($eq($number,1), "member", "members") of $unit($unit) $if($eq($number,1), "is", "are") protected from the cold. ($int36($id))" @@ -335,7 +334,7 @@ - "Ein unbekannter Zauber liegt auf dem Gebude. ($int36($id))" + "Ein unbekannter Zauber liegt auf dem Gebäude. ($int36($id))" "An unknown spell lies on this building. ($int36($id))" @@ -349,7 +348,7 @@ - "Eine Wolke negativer Energie liegt ber der Region. ($int36($id))" + "Eine Wolke negativer Energie liegt über der Region. ($int36($id))" "A fog of negative energy enshrouds the region. ($int36($id))" @@ -372,7 +371,7 @@ - "$unit($unit) strzt sich von einem amoursen Abenteuer ins nchste. ($int36($id))" + "$unit($unit) stürzt sich von einem amourösen Abenteuer ins nächste. ($int36($id))" "$unit($unit) goes from one amourous adventure to another. ($int36($id))" @@ -388,39 +387,50 @@ - "Die Ausrstung von $unit($unit) scheint unsichtbar. ($int36($id))" + "Die Ausrüstung von $unit($unit) scheint unsichtbar. ($int36($id))" "$unit($unit)'s equipment is invisible. ($int36($id))" + - "Die natrliche Widerstandskraft gegen Verzauberung ist gestrkt. ($int36($id))" + "Die natürliche Widerstandskraft gegen Verzauberung ist gestärkt. ($int36($id))" + "The magical resistance has been strengthened. ($int36($id))" + + + + + + + "Die natürliche Widerstandskraft gegen Verzauberung ist gestärkt. ($int36($id))" "The magical resistance has been strengthened. ($int36($id))" - "Die natrliche Widerstandskraft gegen Verzauberung bestimmter Einheiten in dieser Region wurde gestrkt. ($int36($id))" + "Die natürliche Widerstandskraft gegen Verzauberung bestimmter Einheiten in dieser Region wurde gestärkt. ($int36($id))" "The magical resistance of some units in this region was boosted. ($int36($id))" - "Die natrliche Widerstandskraft gegen Verzauberung bestimmter Einheiten in dieser Region wurde geschwcht. ($int36($id))" + "Die natürliche Widerstandskraft gegen Verzauberung bestimmter Einheiten in dieser Region wurde geschwächt. ($int36($id))" "The magical resistance of some units in this region was weakened. ($int36($id))" + - "Diese Mauern wirken, als wren sie direkt aus der Erde gewachsen und nicht erbaut. ($int36($id))" + "Diese Mauern wirken, als wären sie direkt aus der Erde gewachsen und nicht erbaut. ($int36($id))" "These walls appear to have grown straight out of the earth. ($int36($id))" + "Ein magischer Schimmer liegt auf diesen Mauern. ($int36($id))" @@ -430,49 +440,49 @@ - "Die Straen sind erstaunlich trocken und gut begehbar, doch an manchen Stellen bilden sich wieder die erste Schlammlcher. ($int36($id))" + "Die Straßen sind erstaunlich trocken und gut begehbar, doch an manchen Stellen bilden sich wieder die erste Schlammlöcher. ($int36($id))" "The roads are extremely dry and well-kept, but some areas show the first signs of potholes reappearing. ($int36($id))" - "Die Straen sind erstaunlich trocken und gut begehbar. ($int36($id))" + "Die Straßen sind erstaunlich trocken und gut begehbar. ($int36($id))" "The roads are extremely dry and well-kept. ($int36($id))" - "Albtrume plagen die Leute. ($int36($id))" + "Albträume plagen die Leute. ($int36($id))" "Nightmares plague the population. ($int36($id))" - "Die Leute haben schne Trume. ($int36($id))" + "Die Leute haben schöne Träume. ($int36($id))" "The people in this region have sweet dreams. ($int36($id))" - "Diese Region wurde von den Gttern verflucht. Das Meer ist eine ekelige Brhe, braunschwarze, stinkende Gase steigen aus den unergrndlichen Tiefen hervor, und untote Seeungeheuer, Schiffe zerfressend und giftige grne Galle geifernd, sind der Schrecken aller Seeleute, die diese Gewsser durchqueren. Niemand kann hier lange berleben. ($int36($id))" + "Diese Region wurde von den Göttern verflucht. Das Meer ist eine ekelige Brühe, braunschwarze, stinkende Gase steigen aus den unergründlichen Tiefen hervor, und untote Seeungeheuer, Schiffe zerfressend und giftige grüne Galle geifernd, sind der Schrecken aller Seeleute, die diese Gewässer durchqueren. Niemand kann hier lange überleben. ($int36($id))" "This region was cursed by the gods. The sea is a foul cesspool, noxious gases rise from the deep, undead seamonsters attack all ships. Noone can live here for long. ($int36($id))" - "Diese Region wurde von den Gttern verflucht. Stinkende Nebel ziehen ber die tote Erde und furchtbare Kreaturen ziehen ber das Land. Die Brunnen sind vergiftet, und die wenigen essbaren Frchte sind von einem rosa Pilz berzogen. Niemand kann hier lange berleben. ($int36($id))" + "Diese Region wurde von den Göttern verflucht. Stinkende Nebel ziehen über die tote Erde und furchtbare Kreaturen ziehen über das Land. Die Brunnen sind vergiftet, und die wenigen essbaren Früchte sind von einem rosa Pilz überzogen. Niemand kann hier lange überleben. ($int36($id))" "This region was cursed by the gods. Stinking vapors billow over the dead ground and hideous creatures move about the country. The wells are poisened and the edible plants are covered by a pink fungus. Noone can live here for long. ($int36($id))" - "Ein Schleier der Verwirrung liegt ber der Region. ($int36($id))" + "Ein Schleier der Verwirrung liegt über der Region. ($int36($id))" "A veil of confusion lies over the region. ($int36($id))" @@ -493,7 +503,7 @@ - "Es herrscht eine frhliche und ausgelassene Stimmung. ($int36($id))" + "Es herrscht eine fröhliche und ausgelassene Stimmung. ($int36($id))" "Everyone in this region seems to be having a very good time. ($int36($id))" @@ -507,14 +517,14 @@ - "Alle Leute in der Region haben Schlafstrungen. ($int36($id))" + "Alle Leute in der Region haben Schlafstörungen. ($int36($id))" "People in this region suffer from insomnia. ($int36($id))" - "In dieser Gegend herrscht eine Drre. ($int36($id))" + "In dieser Gegend herrscht eine Dürre. ($int36($id))" "This region was hit by a drought. ($int36($id))" @@ -535,12 +545,13 @@ - "Untote schrecken vor dieser Region zurck. ($int36($id))" + "Untote schrecken vor dieser Region zurück. ($int36($id))" "The undead turn away from this region. ($int36($id))" + "Der Zahn der Zeit kann diesen Mauern nichts anhaben. ($int36($id))" "Time cannot touch these walls. ($int36($id))" @@ -557,7 +568,7 @@ - "$unit($unit) setzt ein Sonnensegel. Die Geschwindigkeit des Schiffes erhht um $int($speed)." + "$unit($unit) setzt ein Sonnensegel. Die Geschwindigkeit des Schiffes erhöht um $int($speed)." "$unit($unit) sets a solar sail. The ship's speed is increased by $int($speed)." @@ -592,7 +603,7 @@ - "$unit($unit) ffnet eines der Schlsser in $region($region) mit $if($eq($key,1),"dem Achatenen Schlssel","dem Saphirnen Schlssel")." + "$unit($unit) öffnet eines der Schlösser in $region($region) mit $if($eq($key,1),"dem Achatenen Schlüssel","dem Saphirnen Schlüssel")." "$unit($unit) unlocks one of the locks in $region($region) with $if($eq($key,1),"the Agate Key","the Sapphire Key")." @@ -601,7 +612,7 @@ - "$unit($unit) verschliet eines der Schlsser in $region($region) mit $if($eq($key,1),"dem Achatenen Schlssel","dem Saphirnen Schlssel")." + "$unit($unit) verschließt eines der Schlösser in $region($region) mit $if($eq($key,1),"dem Achatenen Schlüssel","dem Saphirnen Schlüssel")." "$unit($unit) locks one of the locks in $region($region) with $if($eq($key,1),"the Agate Key","the Sapphire Key")." @@ -617,14 +628,14 @@ - "SIEG! $if($eq($n,1), "Die Partei $winners hat", "Die Parteien $winners haben") die Siegbedingung fr die erforderliche Zeit erfllt. Das Spiel ist damit beendet." + "SIEG! $if($eq($n,1), "Die Partei $winners hat", "Die Parteien $winners haben") die Siegbedingung für die erforderliche Zeit erfüllt. Das Spiel ist damit beendet." "VICTORY! $if($eq($n,1), "The faction $winners has", "The factions $winners have") fulfilled the victory condition for the necessary time. The game is over." - "Achtung: $faction($faction) hat die Siegbedingungen erfllt und wird in $if($eq($remain,1),"einer Woche","$int($remain) Wochen") zum Sieger erklrt werden." + "Achtung: $faction($faction) hat die Siegbedingungen erfüllt und wird in $if($eq($remain,1),"einer Woche","$int($remain) Wochen") zum Sieger erklärt werden." "Attention: $faction($faction) has fulfilled the victory condition and will be declared winner in $if($eq($remain,1),"one week","$int($remain) weeks")." @@ -633,7 +644,7 @@ - "$unit($unit) wurde in $region($region) von einem GM gelscht: \"$string\"." + "$unit($unit) wurde in $region($region) von einem GM gelöscht: \"$string\"." "$unit($unit) in $region($region) was removed by a GM: \"$string\"." @@ -648,7 +659,7 @@ - "Ein Hauch des Lebens liegt ber der Welt und alle Wesen fhlen sich frisch und erholt." + "Ein Hauch des Lebens liegt über der Welt und alle Wesen fühlen sich frisch und erholt." "Life itself touches the world and all beings are healed." @@ -657,14 +668,14 @@ - "$unit($unit) hat Glck und findet einen Hort von $int($amount) $resource($item,$amount)." + "$unit($unit) hat Glück und findet einen Hort von $int($amount) $resource($item,$amount)." "$unit($unit) luckily finds a cache of $int($amount) $resource($item,$amount)." - "$unit($unit) brennt ein groes Feuerwerk ab und Kaskaden bunter Sterne, leuchtende Wasserflle aus Licht und strahlende Feuerdrachen erhellen den Himmel." + "$unit($unit) brennt ein großes Feuerwerk ab und Kaskaden bunter Sterne, leuchtende Wasserfälle aus Licht und strahlende Feuerdrachen erhellen den Himmel." "A large firework is visible all over the sky." @@ -672,7 +683,7 @@ - "In $region($region) wird ein groes Feuerwerk abgebrannt, welches noch hier zu bewundern ist. Kaskaden bunter Sterne, leuchtende Wasserflle aus Licht und strahlende Feuerdrachen erhellen den Himmel." + "In $region($region) wird ein großes Feuerwerk abgebrannt, welches noch hier zu bewundern ist. Kaskaden bunter Sterne, leuchtende Wasserfälle aus Licht und strahlende Feuerdrachen erhellen den Himmel." "A large firework, visible all over the sky, has been started in $region($region)." @@ -680,7 +691,7 @@ - "Zur Feier des Geburtstags von ${name} brennt $unit($unit) ein groes Feuerwerk ab. Kaskaden bunter Sterne, leuchtende Wasserflle aus Licht und strahlende Feuerdrachen erhellen den Himmel." + "Zur Feier des Geburtstags von ${name} brennt $unit($unit) ein großes Feuerwerk ab. Kaskaden bunter Sterne, leuchtende Wasserfälle aus Licht und strahlende Feuerdrachen erhellen den Himmel." "A large firework in honor of ${name} is visible all over the sky." @@ -689,7 +700,7 @@ - "Zur Feier des Geburtstags von ${name} wird in $region($region) ein groes Feuerwerk abgebrannt, welches noch hier zu bewundern ist. Kaskaden bunter Sterne, leuchtende Wasserflle aus Licht und strahlende Feuerdrachen erhellen den Himmel." + "Zur Feier des Geburtstags von ${name} wird in $region($region) ein großes Feuerwerk abgebrannt, welches noch hier zu bewundern ist. Kaskaden bunter Sterne, leuchtende Wasserfälle aus Licht und strahlende Feuerdrachen erhellen den Himmel." "A large firework in honor of ${name}, visible all over the sky, has been started in $region($region)." @@ -707,7 +718,7 @@ - "$unit($unit) in $region($region): '$order($command)' - $unit($unit) mu mindestens 2 Stufen besser sein als $unit($student)." + "$unit($unit) in $region($region): '$order($command)' - $unit($unit) muß mindestens 2 Stufen besser sein als $unit($student)." "$unit($unit) in $region($region): '$order($command)' - $unit($unit) needs to be at least 2 levels better than $unit($student)." @@ -727,7 +738,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Dafr braucht die Einheit $resources($required)." + "$unit($unit) in $region($region): '$order($command)' - Dafür braucht die Einheit $resources($required)." "$unit($unit) in $region($region): '$order($command)' - For this, the unit needs $resources($required)." @@ -752,7 +763,7 @@ - "Seit $int($age) Wochen Mitglied der Allianz '$name ($int36($id))', angefhrt von $faction($leader)." + "Seit $int($age) Wochen Mitglied der Allianz '$name ($int36($id))', angeführt von $faction($leader)." "Member of '$name ($int36($id))' for $int($age) weeks, led by $faction($leader)." @@ -776,7 +787,7 @@ - "Statistik fr $region($region):" + "Statistik für $region($region):" "Statistics for $region($region):" @@ -797,14 +808,14 @@ - "Luxusgter zum angegebenen Preis: $int($max)" + "Luxusgüter zum angegebenen Preis: $int($max)" "luxury goods at this price: $int($max)" - "Lohn fr Arbeit: $int($max) Silber" + "Lohn für Arbeit: $int($max) Silber" "worker salary: $int($max) silver" @@ -833,7 +844,7 @@ - "Deine Partei hat $int($score) Punkte. Der Durchschnitt fr Parteien hnlichen Alters ist $int($average) Punkte." + "Deine Partei hat $int($score) Punkte. Der Durchschnitt für Parteien ähnlichen Alters ist $int($average) Punkte." "Your faction has a score of $int($score). The average score for similar factions is $int($average)." @@ -841,7 +852,7 @@ - "Report fr $game, $date" + "Report für $game, $date" "Report for $game, $date" @@ -865,7 +876,7 @@ - "Auf dem Markt wird fr $resource($product,0) $int($price) Silber verlangt." + "Auf dem Markt wird für $resource($product,0) $int($price) Silber verlangt." "The local market offers $resource($product,0) at a price of $int($price) silver." @@ -889,7 +900,7 @@ "Auf der Einheit $if($eq($left,1),"liegt","liegen") $int($left) Wirkung$if($eq($left,1),"","en") $resource($potion,1)." - "There are $int($left) use($eq($left,1),"s","") of $resource($potion,1) left." + "There $if($eq($left,1),"is","are") $int($left) $if($eq($left,1),"use","uses") of $resource($potion,1) left." @@ -933,7 +944,7 @@ - "$unit($unit) benutzt einen Talenttrunk und fhlt, wie sein Wissen zunimmt." + "$unit($unit) benutzt einen Talenttrunk und fühlt, wie sein Wissen zunimmt." "$unit($unit) uses a potion of skills and feels his knowledge grow." @@ -960,7 +971,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Dazu bentigt man $resource($missing,0)." + "$unit($unit) in $region($region): '$order($command)' - Dazu benötigt man $resource($missing,0)." "$unit($unit) in $region($region): '$order($command)' - This requires $resource($missing,0)." @@ -980,7 +991,7 @@ - "$unit($unit) in $region($region): '$order($command)' - $race($race,0) knnen nicht neu gruppiert werden." + "$unit($unit) in $region($region): '$order($command)' - $race($race,0) können nicht neu gruppiert werden." "$unit($unit) in $region($region): '$order($command)' - $race($race,0) cannot be regrouped." @@ -990,7 +1001,7 @@ - "$unit($unit) in $region($region): '$order($command)' - $race($race,0) knnen nichts stehelen." + "$unit($unit) in $region($region): '$order($command)' - $race($race,0) können nichts stehelen." "$unit($unit) in $region($region): '$order($command)' - $race($race,0) cannot steal anything." @@ -1043,14 +1054,14 @@ - "Pltzlich lst sich $building($building) in kleine Traumwolken auf." + "Plötzlich löst sich $building($building) in kleine Traumwolken auf." "$building($building) suddenly dissolves into small pink clouds." - "Fr das Gebude $building($building) konnte die ganze Woche kein Unterhalt bezahlt werden." + "Für das Gebäude $building($building) konnte die ganze Woche kein Unterhalt bezahlt werden." "Upkeep for $building($building) could not be paid all week." @@ -1060,7 +1071,7 @@ - "In $region($region) strzte $building($building) ein.$if($road," Beim Einsturz wurde die halbe Strae vernichtet.","")$if($opfer," $int($opfer) Opfer $if($eq($opfer,1),"ist","sind") zu beklagen.","")" + "In $region($region) stürzte $building($building) ein.$if($road," Beim Einsturz wurde die halbe Straße vernichtet.","")$if($opfer," $int($opfer) Opfer $if($eq($opfer,1),"ist","sind") zu beklagen.","")" "$building($building) in $region($region) collapses.$if($road," The collapse ruined half of the road.","")$if($opfer," There are $int($opfer) casualties.","")" @@ -1080,7 +1091,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die einheit kann sich nicht so gut tarnen." + "$unit($unit) in $region($region): '$order($command)' - Die Einheit kann sich nicht so gut tarnen." "$unit($unit) in $region($region): '$order($command)' -The unit cannot hide that well." @@ -1090,7 +1101,7 @@ "$ship($ship) was destroyed by $unit($unit)." - "$ship($ship) wurde von $unit($unit) zerstrt." + "$ship($ship) wurde von $unit($unit) zerstört." @@ -1099,7 +1110,7 @@ "$unit($unit) could not destroy $ship($ship)." - "$unit($unit) konnte $ship($ship) nicht zerstren." + "$unit($unit) konnte $ship($ship) nicht zerstören." @@ -1108,7 +1119,7 @@ "$unit($unit) was detected while trying to destroy $ship($ship)." - "$unit($unit) wurde beim Versuch $ship($ship) zu zerstren entdeckt." + "$unit($unit) wurde beim Versuch $ship($ship) zu zerstören entdeckt." @@ -1116,7 +1127,7 @@ "Somebody attempted to destroy $ship($ship)." - "Es wurde versucht, $ship($ship) zu zerstren." + "Es wurde versucht, $ship($ship) zu zerstören." @@ -1124,7 +1135,7 @@ "$ship($ship) was destroyed." - "$ship($ship) wurde zerstrt." + "$ship($ship) wurde zerstört." @@ -1142,7 +1153,7 @@ - "$unit($unit) berlebt unbeschadet und rettet sich nach $region($region)." + "$unit($unit) überlebt unbeschadet und rettet sich nach $region($region)." "$unit($unit) survives unscathed and makes it to $region($region)." @@ -1183,7 +1194,25 @@ "$unit($unit) drowns in $region($region)." - + + + + + + "$unit($unit) nimmt Schaden durch den Giftelementar in $region($region)." + "$unit($unit) is taking poison damage in $region($region)." + + + + + + + + "$unit($unit) stirbt am Schaden durch den Giftelementar in $region($region)." + "$unit($unit) dies from poison damage taken in $region($region)." + + + @@ -1204,7 +1233,7 @@ - "$unit($unit) schwenkt sein Szepter und sorgt fr Verwirrung und Chaos in der Region." + "$unit($unit) schwenkt sein Szepter und sorgt für Verwirrung und Chaos in der Region." "$unit($unit) waves their scepter and causes chaos and confusion in the region." @@ -1214,12 +1243,12 @@ - "$unit($unit) stolpert bei der Erforschung der Region ber $localize($location). Nhere Durchsuchung frdert ein zerfleddertes altes Buch mit dem Titel '$localize($book)' zu Tage. Der Wissensschub ist enorm." + "$unit($unit) stolpert bei der Erforschung der Region über $localize($location). Nähere Durchsuchung fördert ein zerfleddertes altes Buch mit dem Titel '$localize($book)' zu Tage. Der Wissensschub ist enorm." "$unit($unit) stumbles upon $localize($location) while exploring the region. Closer inspection reveals a torn old book titled '$localize($book)'. The expansion of knowledge is tremendous." - "Ein Alp hat sein Opfer gefunden und springt auf den Rcken von $unit($target)!" + "Ein Alp hat sein Opfer gefunden und springt auf den Rücken von $unit($target)!" "An evil spirit has found its victim and mounts the back of $unit($target)!" @@ -1228,7 +1257,7 @@ - "$unit($unit) fhlt sich von starken magischen Energien durchstrmt. ($int36($id))" + "$unit($unit) fühlt sich von starken magischen Energien durchströmt. ($int36($id))" "Powerful magical energies are pulsing through $unit($unit). ($int36($id))" @@ -1247,7 +1276,7 @@ - "$unit($mage) zaubert $spell($spell): $int($amount) Krieger sind fr einen Moment benommen." + "$unit($mage) zaubert $spell($spell): $int($amount) Krieger sind für einen Moment benommen." "$unit($mage) casts $spell($spell): $int($amount) fighters were momentarily stunned." @@ -1256,7 +1285,7 @@ - "$unit($mage) besnftigt den Bauernaufstand in $region($region)." + "$unit($mage) besänftigt den Bauernaufstand in $region($region)." "$unit($mage) quells the uprising in $region($region)." @@ -1265,7 +1294,7 @@ - "$unit($mage) rief in $region($region) einen Riss in dem Gefge der Magie hervor, der alle magische Kraft aus der Region riss." + "$unit($mage) rief in $region($region) einen Riss in dem Gefüge der Magie hervor, der alle magische Kraft aus der Region riss." "$unit($mage) in $region($region) caused a tear in the fabric of magic, that sucked all magical energies out of the region." @@ -1315,7 +1344,7 @@ - "$unit($mage) zaubert $spell($spell): $int($amount) Krieger wurden eingeschchtert." + "$unit($mage) zaubert $spell($spell): $int($amount) Krieger wurden eingeschüchtert." "$unit($mage) casts $spell($spell): $int($amount) fighters were intimidated." @@ -1343,7 +1372,7 @@ - "$unit($mage) zaubert $spell($spell): Das Kampfgetmmel erstirbt und er kann unbehelligt seines Weges ziehen." + "$unit($mage) zaubert $spell($spell): Das Kampfgetümmel erstirbt und er kann unbehelligt seines Weges ziehen." "$unit($mage) casts $spell($spell): The noise of the battle dies down and the mage is able to slip away unharmed." @@ -1352,7 +1381,7 @@ - "$unit($mage) zaubert $spell($spell): Ein Sturm kommt auf und die Schtzen knnen kaum noch zielen." + "$unit($mage) zaubert $spell($spell): Ein Sturm kommt auf und die Schützen können kaum noch zielen." "$unit($mage) casts $spell($spell): Strong stormwinds are blowing and the archers are having a hard time aiming." @@ -1362,7 +1391,7 @@ - "$unit($mage) zaubert $spell($spell): $int($amount) Krieger schleppten sich mde in den Kampf." + "$unit($mage) zaubert $spell($spell): $int($amount) Krieger schleppten sich müde in den Kampf." "$unit($mage) casts $spell($spell): $int($amount) fighters had trouble staying awake." @@ -1372,7 +1401,7 @@ - "$unit($mage) zaubert $spell($spell): $int($amount) Krieger wurden moralisch gestrkt." + "$unit($mage) zaubert $spell($spell): $int($amount) Krieger wurden moralisch gestärkt." "$unit($mage) casts $spell($spell): $int($amount) fighters had their moral boosted." @@ -1390,7 +1419,7 @@ - "$unit($mage) ruft ein frchterliches Unwetter ber seine Feinde, doch es gab niemanden mehr, den dies treffen konnte." + "$unit($mage) ruft ein fürchterliches Unwetter über seine Feinde, doch es gab niemanden mehr, den dies treffen konnte." "$unit($mage) calls forth a terrible torment over the enemy side, but there was nobody who could be affected by it." @@ -1398,7 +1427,7 @@ - "$unit($mage) ruft ein frchterliches Unwetter ber seine Feinde, doch der magische Regen zeigt keinen Effekt." + "$unit($mage) ruft ein fürchterliches Unwetter über seine Feinde, doch der magische Regen zeigt keinen Effekt." "$unit($mage) causes a terrible storm over the enemy, but the magic rain does not do any harm." @@ -1406,7 +1435,7 @@ - "$unit($mage) ruft ein frchterliches Unwetter ber seine Feinde. Der magischen Regen lsst alles Eisen rosten." + "$unit($mage) ruft ein fürchterliches Unwetter über seine Feinde. Der magischen Regen lässt alles Eisen rosten." "$unit($mage) calls forth a terrible torment over the enemy. The magical rain makes all iron rusty." @@ -1416,7 +1445,7 @@ - "$unit($mage) beschwrt den Alp $unit($alp) fr $unit($target)." + "$unit($mage) beschwört den Alp $unit($alp) für $unit($target)." "$unit($mage) summons the alp $unit($alp) for $unit($target)." @@ -1425,7 +1454,7 @@ - "$unit($mage) kmmert sich um die Verletzten und heilt $int($amount) Verwundete." + "$unit($mage) kümmert sich um die Verletzten und heilt $int($amount) Verwundete." "$unit($mage) sees after the wounded and heals $int($amount)." @@ -1435,7 +1464,7 @@ - "$unit($mage) kmmert sich um die Verletzten und benutzt ein $resource($item,1), um den Zauber zu verstrken. $int($amount) Verwundete werden geheilt." + "$unit($mage) kümmert sich um die Verletzten und benutzt ein $resource($item,1), um den Zauber zu verstärken. $int($amount) Verwundete werden geheilt." "$unit($mage) sees after the wounded and heals $int($amount). A $resource($item,1) improves the spell." @@ -1445,7 +1474,7 @@ - "Mit einem Ritual bindet $unit($mage) die magischen Krfte der Erde von $region($region) in die Mauern von $building($building)." + "Mit einem Ritual bindet $unit($mage) die magischen Kräfte der Erde von $region($region) in die Mauern von $building($building)." "$unit($mage) performs a ritual that binds the magical forces of $region($region) into the walls of $building($building)." @@ -1474,7 +1503,7 @@ - "$unit($mage) beginnt ein Ritual der Wiederbelebung und benutzt ein $resource($item,1), um den Zauber zu verstrken. $int($amount) Krieger stehen von den Toten auf." + "$unit($mage) beginnt ein Ritual der Wiederbelebung und benutzt ein $resource($item,1), um den Zauber zu verstärken. $int($amount) Krieger stehen von den Toten auf." "$unit($mage) begins a ritual of resurrection augmented by a $resource($item,1). $int($amount) warriors rise from the dead." @@ -1482,7 +1511,7 @@ - "$unit($mage) ffnet ein Chaostor." + "$unit($mage) öffnet ein Chaostor." "$unit($mage) opens a chaos gate." @@ -1506,7 +1535,7 @@ - "$unit($mage) erweckt in $region($region) $int($amount) Untote aus ihren Grbern." + "$unit($mage) erweckt in $region($region) $int($amount) Untote aus ihren Gräbern." "$unit($mage) calls $int($amount) undead from their graves in $region($region)." @@ -1515,7 +1544,7 @@ - "$unit($mage) strt in $region($region) die Ruhe der Toten." + "$unit($mage) stört in $region($region) die Ruhe der Toten." "$unit($mage) communicates with the dead in $region($region)." @@ -1523,7 +1552,7 @@ - "$unit($unit) gelingt es, durch die Nebel auf die Realitt zu blicken." + "$unit($unit) gelingt es, durch die Nebel auf die Realität zu blicken." "$unit($unit) manages to catch a glimpse of reality through the fog." @@ -1556,7 +1585,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Eine hhere Macht hindert $unit($unit) daran, das Objekt zu bergeben. 'ES IST DEINS, MEIN KIND. DEINS GANZ ALLEIN'." + "$unit($unit) in $region($region): '$order($command)' - Eine höhere Macht hindert $unit($unit) daran, das Objekt zu übergeben. 'ES IST DEINS, MEIN KIND. DEINS GANZ ALLEIN'." "$unit($unit) in $region($region): '$order($command)' - A higher power prevents $unit($unit) from giving the object away. 'IT IS YOURS MY CHILD. ONLY YOURS.'." @@ -1564,7 +1593,7 @@ - "$unit($unit) sendet ein Stogebet an den Herrn der Schreie." + "$unit($unit) sendet ein Stoßgebet an den Herrn der Schreie." "$unit($unit) sends a prayer to the Lord of Screams." @@ -1586,21 +1615,21 @@ - "Der Eisberg $region($region) treibt an eine Kste." + "Der Eisberg $region($region) treibt an eine Küste." "The iceberg $region($region) drifts onto a coast." - "Die $ship($ship) wird bei einer Kollision mit einem Eisberg zerstrt." + "Die $ship($ship) wird bei einer Kollision mit einem Eisberg zerstört." "The $ship($ship) has been destroyed by a collision with an iceberg." - "Die $ship($ship) wird bei einer Kollision mit einem Eisberg beschdigt." + "Die $ship($ship) wird bei einer Kollision mit einem Eisberg beschädigt." "The $ship($ship) has been damaged by a collision with an iceberg." @@ -1623,14 +1652,14 @@ - "Wir erklren allen $race($race,2) den heiligen Krieg." + "Wir erklären allen $race($race,2) den heiligen Krieg." "We declare jihad on all $race($race,2)." - "Die Gtter erhren $unit($unit)." + "Die Götter erhören $unit($unit)." "The Gods have listened to $unit($unit)." @@ -1638,14 +1667,14 @@ - "Die Gtter gewhren uns die Kraft eines $special($int($level))." + "Die Götter gewähren uns die Kraft eines $special($int($level))." "The Gods grant us the powers of $special ($int($level))." - "Die Gtter gewhren uns die Kraft eines ${special}." + "Die Götter gewähren uns die Kraft eines ${special}." "The Gods grant us the powers of ${special}." @@ -1656,7 +1685,7 @@ - "$unit($unit) verlor $int($fallen) Personen$if($alive,", $int($alive) berlebten","")$if($run," und $int($run) flohen$if($isnull($runto),""," nach $region($runto)")","")." + "$unit($unit) verlor $int($fallen) Personen$if($alive,", $int($alive) überlebten","")$if($run," und $int($run) flohen$if($isnull($runto),""," nach $region($runto)")","")." "$unit($unit) lost $int($fallen) people$if($alive,", $int($alive) survived","")$if($run," and $int($run) fled$if($isnull($runto),""," to $region($runto)")","")." @@ -1665,7 +1694,7 @@ - "$unit($unit) erzielte $int($hits) Treffer und ttete $int($kills) Gegner." + "$unit($unit) erzielte $int($hits) Treffer und tötete $int($kills) Gegner." "$unit($unit) hit $int($hits) times and killed $int($kills) enemies." @@ -1688,7 +1717,7 @@ - "Verwundert blicken die Bauern von $region($region) auf ein neues Gebude." + "Verwundert blicken die Bauern von $region($region) auf ein neues Gebäude." "Flabbergasted, the peasants of $region($region) behold a new building." @@ -1708,7 +1737,7 @@ - "$unit($mage) beschwrt Naturgeister in den Boden von $region($region)." + "$unit($mage) beschwört Naturgeister in den Boden von $region($region)." "$unit($mage) summons natural spirits into the ground of $region($region)." @@ -1734,7 +1763,7 @@ - "$unit($mage) erlst die gequlten Seelen der Toten." + "$unit($mage) erlöst die gequälten Seelen der Toten." "$unit($mage) redeems the tormented souls of the dead." @@ -1776,7 +1805,7 @@ - "$unit($mage) sorgt in $region($region) fr Trbsal unter den Bauern." + "$unit($mage) sorgt in $region($region) für Trübsal unter den Bauern." "$unit($mage) causes great sadness among the peasants of $region($region)." @@ -1786,7 +1815,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Der Magier erschafft ein Traumgebude." + "$unit($unit) in $region($region): '$order($command)' - Der Magier erschafft ein Traumgebäude." "$unit($unit) in $region($region): '$order($command)' - The magician creates an illusionary building." @@ -1807,7 +1836,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Der Elementar ist zu klein, um das Gebude zu tragen." + "$unit($unit) in $region($region): '$order($command)' - Der Elementar ist zu klein, um das Gebäude zu tragen." "$unit($unit) in $region($region): '$order($command)' - The elemental is too small to carry the building." @@ -1829,7 +1858,7 @@ - "$unit($unit) in $region($region): '$order($command)' - $unit($target) ist von unserer Art, das Ritual wre verschwendete Aura." + "$unit($unit) in $region($region): '$order($command)' - $unit($target) ist von unserer Art, das Ritual wäre verschwendete Aura." "$unit($unit) in $region($region): '$order($command)' - $unit($target) is one of our kind, we should not waste aura on this." @@ -1870,7 +1899,7 @@ - "Ein Beben erschttert $building($building). Viele kleine Pseudopodien erheben das Gebude und tragen es in Richtung $direction($direction)." + "Ein Beben erschüttert $building($building). Viele kleine Pseudopodien erheben das Gebäude und tragen es in Richtung $direction($direction)." "An tremor shakes $building($building). Many little pseudopods lift up the building and carry it to $direction($direction)." @@ -1896,7 +1925,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Sphren des Chaos geben dem Magier einen Teil ihrer Kraft." + "$unit($unit) in $region($region): '$order($command)' - Die Sphären des Chaos geben dem Magier einen Teil ihrer Kraft." "$unit($unit) in $region($region): '$order($command)' - The Spheres of Chaos return a part of his power to the magician." @@ -1905,7 +1934,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Der Magier konnte keinen Fluch zerstren." + "$unit($unit) in $region($region): '$order($command)' - Der Magier konnte keinen Fluch zerstören." "$unit($unit) in $region($region): '$order($command)' - The magician could not destroy any curse." @@ -1914,7 +1943,7 @@ - "In $region($region) dehnt $unit($unit) die Zeit fr $int($amount) Personen." + "In $region($region) dehnt $unit($unit) die Zeit für $int($amount) Personen." "In $region($region), $unit($unit) bends time for $int($amount) men." @@ -1925,7 +1954,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Der Magier zerstrt $int($succ) Flche auf ${target}." + "$unit($unit) in $region($region): '$order($command)' - Der Magier zerstört $int($succ) Flüche auf ${target}." "$unit($unit) in $region($region): '$order($command)' - The magician destroys $int($succ) spells on ${target}." @@ -1936,7 +1965,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Der Magier zerstrt den Fluch ($id) auf ${target}." + "$unit($unit) in $region($region): '$order($command)' - Der Magier zerstört den Fluch ($id) auf ${target}." "$unit($unit) in $region($region): '$order($command)' - The magician destroys the spell ($id) on ${target}." @@ -1947,7 +1976,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Der Zauber ist nicht stark genug, um den Fluch ($id) auf ${target} zu zerstren." + "$unit($unit) in $region($region): '$order($command)' - Der Zauber ist nicht stark genug, um den Fluch ($id) auf ${target} zu zerstören." "$unit($unit) in $region($region): '$order($command)' - The spell is not strong enough to destroy the curse ($id) on ${target}." @@ -1955,7 +1984,7 @@ - "$unit($mage) beschwrt einen Giftelementar in $region($region)." + "$unit($mage) beschwört einen Giftelementar in $region($region)." "$unit($mage) summons a poison elemental in $region($region)." @@ -1981,7 +2010,7 @@ - "$unit($mage) belegt $unit($target) mit einem Klteschutz." + "$unit($mage) belegt $unit($target) mit einem Kälteschutz." "$unit($mage) puts protection from cold on $unit($target)." @@ -2006,7 +2035,7 @@ - $if($isnull($mage),"Ein unentdeckter Magier",$unit($mage)) erschuf einen heiligen Hain von $int($amount) Schlingen. + $if($isnull($mage),"Ein unentdeckter Magier",$unit($mage)) erschuf einen heiligen Hain von $int($amount) Schößlingen. $if($isnull($mage),"An unknown magician",$unit($mage)) created a holy forest of $int($amount) young trees. @@ -2020,7 +2049,7 @@ - "$unit($mage) beschwrt die Mchte des Wassers und ein gigantischer Strudel bildet sich." + "$unit($mage) beschwört die Mächte des Wassers und ein gigantischer Strudel bildet sich." "$unit($mage) summons the power of the seas and a giant maelstrom forms." @@ -2028,7 +2057,7 @@ - "$unit($mage) belebt $int($amount) Bume." + "$unit($mage) belebt $int($amount) Bäume." "$unit($mage) animates $int($amount) trees." @@ -2036,7 +2065,7 @@ - "$unit($mage) sorgt fr trockene Straen in $region($region)." + "$unit($mage) sorgt für trockene Straßen in $region($region)." "$unit($mage) creates dry and well-repaired roads in $region($region)." @@ -2044,7 +2073,7 @@ - "$unit($mage) erfleht den Segen der Gtter des Windes und des Wassers fr $ship($ship)." + "$unit($mage) erfleht den Segen der Götter des Windes und des Wassers für $ship($ship)." "$unit($mage) asks the gods of wind and water on behalf of the $ship($ship)." @@ -2070,15 +2099,15 @@ - "$unit($unit) fhlt seine magischen Krfte schwinden und verliert $int($aura) Aura." + "$unit($unit) fühlt seine magischen Kräfte schwinden und verliert $int($aura) Aura." "$unit($unit) feels the powers of magic fade and loses $int($aura) aura." - "$unit($unit) fhlt sich einen Moment seltsam geschwcht." - "$unit($unit) fhlt strangely weakened." + "$unit($unit) fühlt sich einen Moment seltsam geschwächt." + "$unit($unit) fühlt strangely weakened." @@ -2104,8 +2133,8 @@ - "$unit($mage) fand heraus, dass auf $ship($ship) der Zauber $curse($curse) liegt, der noch etwa $int($months) Wochen bestehen bleibt." - "$unit($mage) discovers that $ship($ship) is charmed with $curse($curse), which will last for, about $int($months) more weeks." + "$unit($mage) fand heraus, dass auf $ship($ship) der Zauber '$curse($curse)' liegt, der noch etwa $int($months) Wochen bestehen bleibt." + "$unit($mage) discovers that $ship($ship) is charmed with '$curse($curse)', which will last for, about $int($months) more weeks." @@ -2114,8 +2143,8 @@ - "$unit($mage) fand heraus, dass auf $building($building) der Zauber $curse($curse) liegt, der noch etwa $int($months) Wochen bestehen bleibt." - "$unit($mage) discovers that $building($building) is charmed with $curse($curse), which will last for about $int($months) more weeks." + "$unit($mage) fand heraus, dass auf $building($building) der Zauber '$curse($curse)' liegt, der noch etwa $int($months) Wochen bestehen bleibt." + "$unit($mage) discovers that $building($building) is charmed with '$curse($curse)', which will last for about $int($months) more weeks." @@ -2124,8 +2153,8 @@ - "$unit($mage) fand heraus, dass auf $unit($unit) der Zauber $curse($curse) liegt, der noch etwa $int($months) Wochen bestehen bleibt." - "$unit($mage) discovers that $unit($unit) is charmed with $curse($curse) that will last for about $int($months) more weeks." + "$unit($mage) fand heraus, dass auf $unit($unit) der Zauber '$curse($curse)' liegt, der noch etwa $int($months) Wochen bestehen bleibt." + "$unit($mage) discovers that $unit($unit) is charmed with '$curse($curse)' that will last for about $int($months) more weeks." @@ -2134,8 +2163,8 @@ - "$unit($mage) fand heraus, dass auf $region($region) der Zauber $curse($curse) liegt, der noch etwa $int($months) Wochen bestehen bleibt." - "$unit($mage) discovers that $region($region) is charmed with $curse($curse), which will last for about $int($months) more weeks." + "$unit($mage) fand heraus, dass auf $region($region) der Zauber '$curse($curse)' liegt, der noch etwa $int($months) Wochen bestehen bleibt." + "$unit($mage) discovers that $region($region) is charmed with '$curse($curse)', which will last for about $int($months) more weeks." @@ -2143,8 +2172,8 @@ - "$unit($mage) fand heraus, dass auf $ship($ship) der Zauber $curse($curse) liegt, dessen Kraft ausreicht, um noch Jahrhunderte bestehen zu bleiben." - "$unit($mage) discovers that $ship($ship) is charmed with $curse($curse), which will last for centuries." + "$unit($mage) fand heraus, dass auf $ship($ship) der Zauber '$curse($curse)' liegt, dessen Kraft ausreicht, um noch Jahrhunderte bestehen zu bleiben." + "$unit($mage) discovers that $ship($ship) is charmed with '$curse($curse)', which will last for centuries." @@ -2152,8 +2181,8 @@ - "$unit($mage) fand heraus, dass auf $building($building) der Zauber $curse($curse) liegt, dessen Kraft ausreicht, um noch Jahrhunderte bestehen zu bleiben." - "$unit($mage) discovers that $building($building) is charmed with $curse($curse), which will last for centuries." + "$unit($mage) fand heraus, dass auf $building($building) der Zauber '$curse($curse)' liegt, dessen Kraft ausreicht, um noch Jahrhunderte bestehen zu bleiben." + "$unit($mage) discovers that $building($building) is charmed with '$curse($curse)', which will last for centuries." @@ -2161,8 +2190,8 @@ - "$unit($mage) fand heraus, dass auf $unit($unit) der Zauber $curse($curse) liegt, dessen Kraft ausreicht, um noch Jahrhunderte bestehen zu bleiben." - "$unit($mage) discovers that $unit($unit) is charmed with $curse($curse), which will last for centuries." + "$unit($mage) fand heraus, dass auf $unit($unit) der Zauber '$curse($curse)' liegt, dessen Kraft ausreicht, um noch Jahrhunderte bestehen zu bleiben." + "$unit($mage) discovers that $unit($unit) is charmed with '$curse($curse)', which will last for centuries." @@ -2170,15 +2199,15 @@ - "$unit($mage) fand heraus, dass auf $region($region) der Zauber $curse($curse) liegt, dessen Kraft ausreicht, um noch Jahrhunderte bestehen zu bleiben." - "$unit($mage) discovers that $region($region) is charmed with $curse($curse), which will last for centuries." + "$unit($mage) fand heraus, dass auf $region($region) der Zauber '$curse($curse)' liegt, dessen Kraft ausreicht, um noch Jahrhunderte bestehen zu bleiben." + "$unit($mage) discovers that $region($region) is charmed with '$curse($curse)', which will last for centuries." - "$unit($mage) meint, dass auf $ship($ship) ein Zauber liegt, konnte aber ber den Zauber nichts herausfinden." + "$unit($mage) meint, dass auf $ship($ship) ein Zauber liegt, konnte aber über den Zauber nichts herausfinden." "It appears to $unit($mage) that $ship($ship) is charmed, but no details have been revealed." @@ -2186,7 +2215,7 @@ - "$unit($mage) meint, dass auf $building($building) ein Zauber liegt, konnte aber ber den Zauber nichts herausfinden." + "$unit($mage) meint, dass auf $building($building) ein Zauber liegt, konnte aber über den Zauber nichts herausfinden." "It appears to $unit($mage) that $building($building) is charmed, but no details have been revealed." @@ -2194,7 +2223,7 @@ - "$unit($mage) meint, dass $unit($unit) verzaubert ist, konnte aber ber den Zauber nichts herausfinden." + "$unit($mage) meint, dass $unit($unit) verzaubert ist, konnte aber über den Zauber nichts herausfinden." "It appears to $unit($mage) that $unit($unit) is charmed, but no details have been revealed." @@ -2202,7 +2231,7 @@ - "$unit($mage) meint, dass auf $region($region) ein Zauber liegt, konnte aber ber den Zauber nichts herausfinden." + "$unit($mage) meint, dass auf $region($region) ein Zauber liegt, konnte aber über den Zauber nichts herausfinden." "It appears to $unit($mage) that $region($region) is charmed, but no details have been revealed." @@ -2263,7 +2292,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Gebude $int36($id) konnte nicht verzaubert werden." + "$unit($unit) in $region($region): '$order($command)' - Gebäude $int36($id) konnte nicht verzaubert werden." "$unit($unit) in $region($region): '$order($command)' - Building $int36($id) could not be charmed." @@ -2293,7 +2322,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Gebude $int36($id) wurde nicht gefunden." + "$unit($unit) in $region($region): '$order($command)' - Gebäude $int36($id) wurde nicht gefunden." "$unit($unit) in $region($region): '$order($command)' - Building $int36($id) could not be located." @@ -2339,7 +2368,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Fr diesen Zauber fehlen noch $resources($list)." + "$unit($unit) in $region($region): '$order($command)' - Für diesen Zauber fehlen noch $resources($list)." "$unit($unit) in $region($region): '$order($command)' - Casting this spell requires an additional $resources($list)." @@ -2348,7 +2377,7 @@ - "$unit($unit) hat nicht gengend Komponenten um $spell($spell) auf Stufe $int($level) zu zaubern." + "$unit($unit) hat nicht genügend Komponenten um $spell($spell) auf Stufe $int($level) zu zaubern." "$unit($unit) has insufficient components to cast $spell($spell) on level $int($level)." @@ -2357,7 +2386,7 @@ - "$unit($unit) unterluft in $region($region) beim Zaubern von $spell($spell) ein Patzer." + "$unit($unit) unterläuft in $region($region) beim Zaubern von $spell($spell) ein Patzer." "$unit($unit) fumbles while casting $spell($spell) in $region($region)." @@ -2366,7 +2395,7 @@ - "Als $unit($unit) in $region($region) versucht, $spell($spell) zu zaubern, scheint pltzlich ein Beben durch die magische Essenz zu laufen und ein furchtbarer Sog versucht $unit($unit) in eine andere Dimension zu ziehen. Mit letzter Kraft gelingt es $unit($unit) sich zu retten." + "Als $unit($unit) in $region($region) versucht, $spell($spell) zu zaubern, scheint plötzlich ein Beben durch die magische Essenz zu laufen und ein furchtbarer Sog versucht $unit($unit) in eine andere Dimension zu ziehen. Mit letzter Kraft gelingt es $unit($unit) sich zu retten." "When $unit($unit) in $region($region) tries to cast $spell($spell), a sudden disturbance ripples through the magical realm and a terrible force attempts to drag the magician to another dimension. However, with a final effort of strength, $unit($unit) manages to save himself." @@ -2375,7 +2404,7 @@ - "Als $unit($unit) in $region($region) versucht, $spell($spell) zu zaubern erhebt sich pltzlich ein dunkler Wind. Bizarre geisterhafte Gestalten kreisen um den Magier und scheinen sich von den magischen Energien des Zaubers zu ernhren. Mit letzter Kraft gelingt es $unit($unit) dennoch den Spruch zu zaubern." + "Als $unit($unit) in $region($region) versucht, $spell($spell) zu zaubern erhebt sich plötzlich ein dunkler Wind. Bizarre geisterhafte Gestalten kreisen um den Magier und scheinen sich von den magischen Energien des Zaubers zu ernähren. Mit letzter Kraft gelingt es $unit($unit) dennoch den Spruch zu zaubern." "When $unit($unit) in $region($region) tries to cast $spell($spell), strong winds suddenly rise. Bizarre ghostlike creatures circle around the magician and seem to be leeching magical energy. However, with a final effort of strength, $unit($unit) manages to complete the spell." @@ -2394,7 +2423,7 @@ - "$unit($unit) in $region($region): '$order($command)' - $unit($mage) kann Zauber, die durch $unit($unit) gewirkt werden, nicht zustzlich in die Ferne richten." + "$unit($unit) in $region($region): '$order($command)' - $unit($mage) kann Zauber, die durch $unit($unit) gewirkt werden, nicht zusätzlich in die Ferne richten." "$unit($unit) in $region($region): '$order($command)' - $unit($mage) cannot direct spells that are channeled through $unit($unit) into distant regions." @@ -2413,7 +2442,7 @@ - "$unit($mage) ruft einen Vertrauten. $race($race, 0) knnen $skills lernen." + "$unit($mage) ruft einen Vertrauten. $race($race, 0) können $skills lernen." "$unit($mage) summons a familiar. $race($race, 0) can learn ${skills}." @@ -2422,7 +2451,7 @@ - "$unit($unit) hat einen feuchtfrhlichen Abend in der Taverne verbracht. Ausser einem frchterlichen Brummschdel ist da auch noch das dumme Gefhl $unit($mage) seine ganze Lebensgeschichte erzhlt zu haben." + "$unit($unit) hat einen feuchtfröhlichen Abend in der Taverne verbracht. Ausser einem fürchterlichen Brummschädel ist da auch noch das dumme Gefühl $unit($mage) seine ganze Lebensgeschichte erzählt zu haben." "$unit($unit) spent the evening carousing in the tavern. In addition to a terrible headache, there remains this feeling of having told $unit($mage) the story of his entire life." @@ -2430,7 +2459,7 @@ - "$unit($unit) hat einen feuchtfrhlichen Abend in der Taverne verbracht. Ausser einem frchterlichen Brummschdel ist da auch noch das dumme Gefhl die ganze Taverne mit seiner Lebensgeschichte unterhalten zu haben." + "$unit($unit) hat einen feuchtfröhlichen Abend in der Taverne verbracht. Ausser einem fürchterlichen Brummschädel ist da auch noch das dumme Gefühl die ganze Taverne mit seiner Lebensgeschichte unterhalten zu haben." "$unit($unit) spent the evening carousing in the tavern. In addition to a terrible headache, there remains this feeling of having told everyone the story of his entire life." @@ -2440,7 +2469,7 @@ - "$unit($mage) gelingt es $unit($unit) zu verzaubern. $unit($unit) wird fr etwa $int($duration) Wochen unseren Befehlen gehorchen." + "$unit($mage) gelingt es $unit($unit) zu verzaubern. $unit($unit) wird für etwa $int($duration) Wochen unseren Befehlen gehorchen." "$unit($mage) chamrs $unit($unit). $unit($unit) will obey our orders for approximatley $int($duration) more weeks." @@ -2459,7 +2488,7 @@ - "$unit($unit) fhlt sich nach dem Zaubern von $spell($spell) viel erschpfter als sonst und hat das Gefhl, dass alle weiteren Zauber deutlich mehr Kraft als normalerweise kosten werden." + "$unit($unit) fühlt sich nach dem Zaubern von $spell($spell) viel erschöpfter als sonst und hat das Gefühl, dass alle weiteren Zauber deutlich mehr Kraft als normalerweise kosten werden." "$unit($unit) feels far more exhausted than he should after casting $spell($spell) and assumes that any following spells will cost far more energy than usual." @@ -2467,7 +2496,7 @@ - "$unit($unit) in $region($region) hat rasende Kopfschmerzen und kann sich nicht mehr richtig konzentrieren. Irgendwas bei diesem Zauber ist frchterlich schiefgelaufen." + "$unit($unit) in $region($region) hat rasende Kopfschmerzen und kann sich nicht mehr richtig konzentrieren. Irgendwas bei diesem Zauber ist fürchterlich schiefgelaufen." "$unit($unit) in $region($region) is hit by a massive headache and cannot concentrate on the spell. Some part of this ritual has gone very wrong indeed." @@ -2476,7 +2505,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Der Magier verfngt sich im eigenen Zauber." + "$unit($unit) in $region($region): '$order($command)' - Der Magier verfängt sich im eigenen Zauber." "$unit($unit) in $region($region): '$order($command)' - The magician is caught in their own spell." @@ -2489,7 +2518,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Der Zauber von $unit.dative($unit) war viel zu schwach und lst sich gleich wieder auf." + "$unit($unit) in $region($region): '$order($command)' - Der Zauber von $unit.dative($unit) war viel zu schwach und löst sich gleich wieder auf." "$unit($unit) in $region($region): '$order($command)' - The spell of $unit($unit) was way to weak and its magic dissolves immediately." @@ -2525,7 +2554,7 @@ - "$unit($mage) erhht die Krperkraft von $unit.dative($target) betrchtlich." + "$unit($mage) erhöht die Körperkraft von $unit.dative($target) beträchtlich." "$unit($mage) increases the strength of $unit($target) dramatically." @@ -2551,7 +2580,7 @@ - "$unit($unit) in $region($region) verbraucht $int($cost) Silber fr das Studium von $skill($skill)." + "$unit($unit) in $region($region) verbraucht $int($cost) Silber für das Studium von $skill($skill)." "$unit($unit) spends $int($cost) silver in $region($region) to study $skill($skill)." @@ -2559,7 +2588,7 @@ - "$unit($teacher) kann durch Dumpfbackenbrot nur $int($amount) Schler lehren." + "$unit($teacher) kann durch Dumpfbackenbrot nur $int($amount) Schüler lehren." "Due to the effect of duncebuns, $unit($teacher) can only teach $int($amount) students." @@ -2611,7 +2640,7 @@ - "$unit($unit) bezahlt $int($money) Silber fr den Kauf von Luxusgtern." + "$unit($unit) bezahlt $int($money) Silber für den Kauf von Luxusgütern." "$unit($unit) pays $int($money) silver for luxury items." @@ -2620,7 +2649,7 @@ - "$unit($unit) verdient in $region($region) $int($amount) Silber durch den Verkauf von Luxusgtern." + "$unit($unit) verdient in $region($region) $int($amount) Silber durch den Verkauf von Luxusgütern." "$unit($unit) earned $int($amount) silver in $region($region) by selling luxury items." @@ -2630,7 +2659,7 @@ - "$unit($unit) arbeitet in $region($region) fr einen Lohn von $int($amount)$if($eq($wanted,$amount),""," statt $int($wanted)") Silber." + "$unit($unit) arbeitet in $region($region) für einen Lohn von $int($amount)$if($eq($wanted,$amount),""," statt $int($wanted)") Silber." "$unit($unit) works in $region($region) for a wage of $int($amount) $if($eq($wanted,$amount),""," out of $int($wanted)") silver." @@ -2639,7 +2668,7 @@ - "$unit($unit) arbeitet in $region($region) fr einen Lohn von $int($amount) Silber." + "$unit($unit) arbeitet in $region($region) für einen Lohn von $int($amount) Silber." "In $region($region), $unit($unit) works for a wage of $int($amount) silver." @@ -2658,7 +2687,7 @@ - "$unit($unit) fngt in $region($region) Fische im Wert von $int($amount) Silber." + "$unit($unit) fängt in $region($region) Fische im Wert von $int($amount) Silber." "In $region($region), $unit($unit) catches fish worth $int($amount) silver." @@ -2715,7 +2744,7 @@ - "$unit($unit) treibt in $region($region) Steuern in Hhe von $int($amount)$if($eq($wanted,$amount),""," statt $int($wanted)") Silber ein." + "$unit($unit) treibt in $region($region) Steuern in Höhe von $int($amount)$if($eq($wanted,$amount),""," statt $int($wanted)") Silber ein." "$unit($unit) collects taxes of$if($eq($wanted,$amount),""," only") $int($amount) silver$if($eq($wanted,$amount),""," instead of $int($wanted) silver") ") in $region($region)." @@ -2724,7 +2753,7 @@ - "$unit($unit) treibt in $region($region) Steuern in Hhe von $int($amount) Silber ein." + "$unit($unit) treibt in $region($region) Steuern in Höhe von $int($amount) Silber ein." "$unit($unit) collects taxes of $int($amount) silver in $region($region)." @@ -2735,7 +2764,7 @@ - "$unit($unit) verdient$if($eq($mode,4)," am Handel","") in $region($region) $int($amount)$if($eq($wanted,$amount),""," statt $int($wanted)") Silber$if($eq($mode,1)," durch Unterhaltung",$if($eq($mode,2)," durch Steuern",$if($eq($mode,3)," durch Handel",$if($eq($mode,5)," durch Diebstahl",$if($eq($mode,6)," durch Zauberei",$if($eq($mode,7)," durch Plndern",""))))))." + "$unit($unit) verdient$if($eq($mode,4)," am Handel","") in $region($region) $int($amount)$if($eq($wanted,$amount),""," statt $int($wanted)") Silber$if($eq($mode,1)," durch Unterhaltung",$if($eq($mode,2)," durch Steuern",$if($eq($mode,3)," durch Handel",$if($eq($mode,5)," durch Diebstahl",$if($eq($mode,6)," durch Zauberei",$if($eq($mode,7)," durch Plündern",""))))))." "$unit($unit) earns $int($amount)$if($eq($wanted,$amount),""," of $int($wanted)") in $region($region) $if($eq($mode,1)," by entertainment",$if($eq($mode,2)," by taxes",$if($eq($mode,3)," by trade",$if($eq($mode,5)," by stealing",$if($eq($mode,6)," by magic",$if($eq($mode,7)," by pillaging",""))))))." @@ -2753,7 +2782,7 @@ - "$unit($unit) zchtet $int($amount) Pferde." + "$unit($unit) züchtet $int($amount) Pferde." "$unit($unit) breeds $int($amount) horses." @@ -2778,7 +2807,7 @@ - "Die Laenader in $region($region) ist erschpft." + "Die Laenader in $region($region) ist erschöpft." "There is no more laen left in $region($region)." @@ -2801,24 +2830,13 @@ "$unit($unit) in $region($region) produziert $int($amount)$if($eq($wanted,$amount),""," von $int($wanted)") $resource($resource,$wanted)." "$unit($unit) in $region($region) produces $int($amount)$if($eq($wanted,$amount),""," of $int($wanted)") $resource($resource,$amount)." - - - - - - - - - "$unit($unit) in $region($region) produziert $int($amount)$if($eq($wanted,$amount),""," von $int($wanted)") $resource($resource,$wanted)." - "$unit($unit) in $region($region) produces $int($amount)$if($eq($wanted,$amount),""," of $int($wanted)") $resource($resource,$amount)." - - "$unit($unit) baut fr $int($size) an $building($building) weiter." + "$unit($unit) baut für $int($size) an $building($building) weiter." "$unit($unit) builds $int($size) more on $building($building)." @@ -2827,7 +2845,7 @@ - "$unit($unit) baut fr $int($size) an $ship($ship) weiter." + "$unit($unit) baut für $int($size) an $ship($ship) weiter." "$unit($unit) builds $int($size) more on $ship($ship)." @@ -2903,7 +2921,7 @@ - "Die Mannschaft der $ship($ship) kann in letzter Sekunde verhindern, dass das Schiff in $region($region) auf Land aufluft." + "Die Mannschaft der $ship($ship) kann in letzter Sekunde verhindern, dass das Schiff in $region($region) auf Land aufläuft." "At the very last moment, the crew of the $ship($ship) saved the ship from running aground in $region($region)." @@ -2911,7 +2929,7 @@ - "Die $ship($ship) konnte in $region($region) nicht einreisen, die Kste ist zu gefhrlich fr das Schiff." + "Die $ship($ship) konnte in $region($region) nicht einreisen, die Küste ist zu gefährlich für das Schiff." "The $ship($ship) could not berth in $region($region). The coast is too dangerous for the vessel." @@ -2981,14 +2999,14 @@ - "Wir haben $faction($faction) den Krieg erklrt." + "Wir haben $faction($faction) den Krieg erklärt." "We declared war on $faction($faction)." - "$faction($faction) hat uns den Krieg erklrt." + "$faction($faction) hat uns den Krieg erklärt." "$faction($faction) has declared war on us." @@ -3052,14 +3070,14 @@ - "In $region($region) erschienen die Herren der Bume." + "In $region($region) erschienen die Herren der Bäume." "In $region($region), the Lords of the Trees have risen." - "In $region($region) erhoben sich die Toten aus den Grbern." + "In $region($region) erhoben sich die Toten aus den Gräbern." "The dead rise from their graves in $region($region)." @@ -3155,8 +3173,8 @@ - "Der Vulkan in $region($regionv) bricht aus. Die Lavamassen verwsten $region($regionn)." - "The volcano in $region($regionv) erupts. The lava devastates $region($region)." + "Der Vulkan in $region($regionv) bricht aus. Die Lavamassen verwüsten $region($regionn)." + "The volcano in $region($regionv) erupts. The lava devastates $region($regionn)." @@ -3178,7 +3196,7 @@ - "Aus dem Vulkankrater von $region($region) steigt pltzlich Rauch." + "Aus dem Vulkankrater von $region($region) steigt plötzlich Rauch." "Columns of smoke are released by the volcano of $region($region)." @@ -3195,7 +3213,7 @@ - "$unit($unit) reit die Strae zwischen $region($from) und $region($to) ein." + "$unit($unit) reißt die Straße zwischen $region($from) und $region($to) ein." "$unit($unit) demolishes the road between $region($from) and $region($to)." @@ -3203,7 +3221,7 @@ - "$unit($unit) in $region($region) kann keine Kruter finden." + "$unit($unit) in $region($region) kann keine Kräuter finden." "$unit($unit) could not find any herbs in $region($region)." @@ -3221,7 +3239,7 @@ - "$unit($unit) reit einen Teil von $building($building) ein." + "$unit($unit) reißt einen Teil von $building($building) ein." "$unit($unit) tears down parts of $building($building)." @@ -3229,7 +3247,7 @@ - "$unit($unit) zerstrt $building($building)." + "$unit($unit) zerstört $building($building)." "$unit($unit) destroys $building($building)." @@ -3238,7 +3256,7 @@ - "$unit($unit) erweitert in $region($region) das Straennetz um $int($size)." + "$unit($unit) erweitert in $region($region) das Straßennetz um $int($size)." "$unit($unit) extends the road network in $region($region) by $int($size)." @@ -3247,7 +3265,7 @@ - "$unit($unit) $if($eq($amount,1),"schliet","schlieen") sich $int($amount) $resource($rtype,$amount) an." + "$unit($unit) $if($eq($amount,1),"schließt","schließen") sich $int($amount) $resource($rtype,$amount) an." "$int($amount) $resource($rtype,$amount) $if($eq($amount,1),"joins","join") $unit($unit)." @@ -3255,7 +3273,7 @@ - "$unit($mage) legt einen Schleier um die Ausrstung von $unit.dative($target)." + "$unit($mage) legt einen Schleier um die Ausrüstung von $unit.dative($target)." "$unit($mage) shrouds the equipment of $unit($target) in shadows." @@ -3279,7 +3297,7 @@ - "Langsam kehren andere Vlker nach $region($region) zurck." + "Langsam kehren andere Völker nach $region($region) zurück." "Little by little, people return to $region($region)." @@ -3295,7 +3313,7 @@ - "$unit($unit) in $region($region) beschdigt die $ship($ship)." + "$unit($unit) in $region($region) beschädigt die $ship($ship)." "$unit($unit) in $region($region) damages the $ship($ship)." @@ -3311,21 +3329,21 @@ - "$unit($unit) marschiert in eine Antimagiezone und lst sich auf." + "$unit($unit) marschiert in eine Antimagiezone und löst sich auf." "$unit($unit) walks into an antimagical zone and dissolves." - "$unit($unit) hat sich unbemerkt verflchtigt." + "$unit($unit) hat sich unbemerkt verflüchtigt." "$unit($unit) has dissolved without a trace." - "$unit($unit) wird sich bald verflchtigen." + "$unit($unit) wird sich bald verflüchtigen." "$unit($unit) will dissolve soon." @@ -3373,28 +3391,28 @@ - "Das Passwort fr diese Partei lautet ${value}." + "Das Passwort für diese Partei lautet ${value}." "The password of this faction is '$value'." - "Die Reportadresse wurde nicht gendert, '${value}' ist keine gltige email." + "Die Reportadresse wurde nicht geändert, '${value}' ist keine gültige email." "Address not changed, '$value' is an invalid email." - "Die Reportadresse wurde auf ${value} gendert." + "Die Reportadresse wurde auf ${value} geändert." "Address has been changed to '$value'." - "Das Banner wurde auf '$value' gendert." + "Das Banner wurde auf '$value' geändert." "Banner has been changed to '$value'." @@ -3404,7 +3422,7 @@ - "Eine Partei mu mindestens $int($turns) Wochen alt sein, bevor sie angegriffen oder bestohlen werden kann." + "Eine Partei muß mindestens $int($turns) Wochen alt sein, bevor sie angegriffen oder bestohlen werden kann." "A faction must be at least $int($turns) weeks old before it can be attacked or stolen from." @@ -3413,7 +3431,7 @@ - "$unit($unit) wurden in $region($region) $int($amount) Silberstcke geklaut." + "$unit($unit) wurden in $region($region) $int($amount) Silberstücke geklaut." "In $region($region), thieves stole $int($amount) silver from $unit($unit)." @@ -3436,7 +3454,7 @@ - "$unit($unit) fhlt sich beobachtet." + "$unit($unit) fühlt sich beobachtet." "$unit($unit) feels watched." @@ -3452,7 +3470,7 @@ - "$unit($spy) gelang es nicht, etwas ber $unit($target) herauszufinden." + "$unit($spy) gelang es nicht, etwas über $unit($target) herauszufinden." "$unit($spy) could not find out anything about $unit($target)." @@ -3461,19 +3479,21 @@ - "$unit($spy) gelang es, Informationen ber $unit($target) herauszubekommen: Kampfstatus $status." - "$unit($spy) managed to gather information about $unit($target): combat status ($status)." + "$unit($spy) gelang es, Informationen über $unit($target) herauszubekommen: Kampfstatus ${status}." + "$unit($spy) managed to gather information about $unit($target): combat status ${status}." + - "$unit($target) ist ein $type-Magier." - "$unit($target) is a $type-magician" + "$unit($target) ist ein ${type}-Magier." + "$unit($target) is a ${type}-magician" + @@ -3482,10 +3502,11 @@ + - "Im Gepck von $unit($target) sind $resources($items)." + "Im Gepäck von $unit($target) sind $resources($items)." "$unit($target) carries $resources($items)" @@ -3494,7 +3515,7 @@ - "$unit($target) gehrt der Partei $faction($faction) an." + "$unit($target) gehört der Partei $faction($faction) an." "$unit($target) belongs to $faction($faction)." @@ -3502,7 +3523,7 @@ - "$unit($target) fhlt sich $if($isnull($spy),"","durch $unit($spy) ")beobachtet." + "$unit($target) fühlt sich $if($isnull($spy),"","durch $unit($spy) ")beobachtet." "$unit($target) feels watched$if($isnull($spy),""," by $unit($spy)")." @@ -3528,7 +3549,7 @@ - "$unit($unit) in $region($region) wird durch unzureichende Nahrung geschwcht." + "$unit($unit) in $region($region) wird durch unzureichende Nahrung geschwächt." "$unit($unit) is weakened due to malnourishment." @@ -3538,7 +3559,7 @@ - "$unit($unit) verliert in $region($region) $int($dead) von $int($add($live,$dead)) Personen durch Unterernhrung." + "$unit($unit) verliert in $region($region) $int($dead) von $int($add($live,$dead)) Personen durch Unterernährung." "$unit($unit) loses $int($dead) of $int($add($live,$dead)) people due to starvation in $region($region)." @@ -3561,7 +3582,7 @@ - "Die $ship($ship) ist zu stark beschdigt und sinkt." + "Die $ship($ship) ist zu stark beschädigt und sinkt." "The $ship($ship) has suffered too much damage and sinks." @@ -3596,7 +3617,7 @@ - "Die $ship($ship) wird in $region($region) von Strmen abgetrieben$if($sink," und sinkt","")." + "Die $ship($ship) wird in $region($region) von Stürmen abgetrieben$if($sink," und sinkt","")." "The $ship($ship) in $region($region) gets off course in heavy storm$if($sink," and sinks","")." @@ -3606,7 +3627,7 @@ - "Die $ship($ship) fhrt in den Mahlstrom von $region($region) und nimmt $int($damage) Schaden$if($sink," und sinkt","")." + "Die $ship($ship) fährt in den Mahlstrom von $region($region) und nimmt $int($damage) Schaden$if($sink," und sinkt","")." "The $ship($ship) sails into the maelstrom of $region($region) and takes $int($damage) damage$if($sink,". The ship sinks","")." @@ -3650,7 +3671,7 @@ - "$unit($unit) belagert $building($building). Dabei richten die Katapulte Zerstrungen von $int($destruction) Grenpunkten an." + "$unit($unit) belagert $building($building). Dabei richten die Katapulte Zerstörungen von $int($destruction) Größenpunkten an." "$building($building) is under siege by $unit($unit). During siege, catapults caused $int($destruction) points destruction." @@ -3689,7 +3710,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Einheit kann den Befehl in dieser Runde nicht ausfhren, da sie an einem Kampf teilgenommen hat." + "$unit($unit) in $region($region): '$order($command)' - Die Einheit kann den Befehl in dieser Runde nicht ausführen, da sie an einem Kampf teilgenommen hat." "$unit($unit) in $region($region): '$order($command)' - The unit cannot execute this command because it has been in combat." @@ -3699,7 +3720,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Das Gebude kann nur einmal pro Runde erweitert werden." + "$unit($unit) in $region($region): '$order($command)' - Das Gebäude kann nur einmal pro Runde erweitert werden." "$unit($unit) in $region($region): '$order($command)' - The building can be expanded only once per turn." @@ -3709,7 +3730,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Dieses Objekt ist unzerstrbar." + "$unit($unit) in $region($region): '$order($command)' - Dieses Objekt ist unzerstörbar." "$unit($unit) in $region($region): '$order($command)' - This object is indestructible." @@ -3745,7 +3766,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Werwesen knnen nicht arbeiten." + "$unit($unit) in $region($region): '$order($command)' - Werwesen können nicht arbeiten." "$unit($unit) in $region($region): '$order($command)' - Lycantropes don't work." @@ -3754,7 +3775,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Werwesen knnen nicht mit anderen Personen gemischt werden." + "$unit($unit) in $region($region): '$order($command)' - Werwesen können nicht mit anderen Personen gemischt werden." "$unit($unit) in $region($region): '$order($command)' - Lycantropes may not be mixed with normal people." @@ -3790,7 +3811,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Dieses Talent kann nicht hher gelernt werden." + "$unit($unit) in $region($region): '$order($command)' - Dieses Talent kann nicht höher gelernt werden." "$unit($unit) in $region($region): '$order($command)' - This skill cannot be raised any higher." @@ -3808,7 +3829,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Partei mu mindestens 9 Wochen alt sein, um einen Neustart zu versuchen." + "$unit($unit) in $region($region): '$order($command)' - Die Partei muß mindestens 9 Wochen alt sein, um einen Neustart zu versuchen." "$unit($unit) in $region($region): '$order($command)' - Your faction is not old enough to start over." @@ -3817,7 +3838,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Optionen ZIP und BZIP2 knnen nur um-, nicht ausgeschaltet werden." + "$unit($unit) in $region($region): '$order($command)' - Die Optionen ZIP und BZIP2 können nur um-, nicht ausgeschaltet werden." "$unit($unit) in $region($region): '$order($command)' - Options ZIP and BZIP2 can only be switched, not turned off." @@ -3826,7 +3847,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Einheiten einer Partei, die noch immun gegen Angriffe ist, drfen nicht bewachen." + "$unit($unit) in $region($region): '$order($command)' - Einheiten einer Partei, die noch immun gegen Angriffe ist, dürfen nicht bewachen." "$unit($unit) in $region($region): '$order($command)' - Units of a faction that can't be attacked may not guard." @@ -3862,7 +3883,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Ungltiges Synonym." + "$unit($unit) in $region($region): '$order($command)' - Ungültiges Synonym." "$unit($unit) in $region($region): '$order($command)' - Invalid synonym." @@ -3871,7 +3892,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Ungltiges Prefix." + "$unit($unit) in $region($region): '$order($command)' - Ungültiges Prefix." "$unit($unit) in $region($region): '$order($command)' - Invalid prefix." @@ -3889,7 +3910,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Gebude auf dem Ozean knnen nicht betreten werden." + "$unit($unit) in $region($region): '$order($command)' - Gebäude auf dem Ozean können nicht betreten werden." "$unit($unit) in $region($region): '$order($command)' - Buildings on the ocean may not be entered." @@ -3898,7 +3919,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Hier werden niemals Bume wachsen." + "$unit($unit) in $region($region): '$order($command)' - Hier werden niemals Bäume wachsen." "$unit($unit) in $region($region): '$order($command)' - Trees won't grow here." @@ -3916,7 +3937,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Verbnde knnen nur zwischen Einheiten derselben Partei gebildet werden." + "$unit($unit) in $region($region): '$order($command)' - Verbände können nur zwischen Einheiten derselben Partei gebildet werden." @@ -3949,7 +3970,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Wieviel sollen wir einreien?" + "$unit($unit) in $region($region): '$order($command)' - Wieviel sollen wir einreißen?" "$unit($unit) in $region($region): '$order($command)' - How much shall we tear down?" @@ -3958,7 +3979,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Dorthin knnen wir die Einheit nicht transportieren." + "$unit($unit) in $region($region): '$order($command)' - Dorthin können wir die Einheit nicht transportieren." "$unit($unit) in $region($region): '$order($command)' - We cannot transport this unit there." @@ -3985,7 +4006,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Nur noch nicht gestrkte Untote knnen das Ziel dieses Zaubers sein." + "$unit($unit) in $region($region): '$order($command)' - Nur noch nicht gestärkte Untote können das Ziel dieses Zaubers sein." "$unit($unit) in $region($region): '$order($command)' - Undead can only be affected once by this spell." @@ -4029,7 +4050,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Name und Beschreibung des Gebudes knnen nicht gendert werden." + "$unit($unit) in $region($region): '$order($command)' - Name und Beschreibung des Gebäudes können nicht geändert werden." "$unit($unit) in $region($region): '$order($command)' - You cannot change the name and description of this building." @@ -4056,7 +4077,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Hier kann man keine Gebude errichten." + "$unit($unit) in $region($region): '$order($command)' - Hier kann man keine Gebäude errichten." "$unit($unit) in $region($region): '$order($command)' - Buildings cannot be built here." @@ -4083,7 +4104,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Pferde mssen leider drauen bleiben." + "$unit($unit) in $region($region): '$order($command)' - Pferde müssen leider draußen bleiben." "$unit($unit) in $region($region): '$order($command)' - Horses are not allowed inside." @@ -4118,7 +4139,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Hier kann man nichts bergeben." + "$unit($unit) in $region($region): '$order($command)' - Hier kann man nichts übergeben." "$unit($unit) in $region($region): '$order($command)' - You cannot transfer items here." @@ -4181,7 +4202,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Vor den Besitzer eines Schiffes oder Gebudes kann nicht sortiert werden." + "$unit($unit) in $region($region): '$order($command)' - Vor den Besitzer eines Schiffes oder Gebäudes kann nicht sortiert werden." "$unit($unit) in $region($region): '$order($command)' - You cannot sort before the owner of a ship or a building." @@ -4190,7 +4211,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Der Besitzer eines Schiffes oder Gebudes kann nicht neu sortiert werden." + "$unit($unit) in $region($region): '$order($command)' - Der Besitzer eines Schiffes oder Gebäudes kann nicht neu sortiert werden." "$unit($unit) in $region($region): '$order($command)' - The owner of a ship or a building cannot be sorted." @@ -4199,7 +4220,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Der Befehl ist nur auf Einheiten innerhalb des selben Gebudes oder Schiffes anwendbar." + "$unit($unit) in $region($region): '$order($command)' - Der Befehl ist nur auf Einheiten innerhalb des selben Gebäudes oder Schiffes anwendbar." "$unit($unit) in $region($region): '$order($command)' - That order only applies to units in the same building or ship." @@ -4208,7 +4229,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Zieleinheit ist ungltig." + "$unit($unit) in $region($region): '$order($command)' - Die Zieleinheit ist ungültig." "$unit($unit) in $region($region): '$order($command)' - The target unit is invalid." @@ -4217,7 +4238,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Ungltiges Locale." + "$unit($unit) in $region($region): '$order($command)' - Ungültiges Locale." "$unit($unit) in $region($region): '$order($command)' - Invalid locale." @@ -4253,7 +4274,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Der Magier ist nicht stark genug, sich den Gttern zu opfern." + "$unit($unit) in $region($region): '$order($command)' - Der Magier ist nicht stark genug, sich den Göttern zu opfern." "$unit($unit) in $region($region): '$order($command)' - This magician is not strong enough to be sacrificed to the gods." @@ -4271,7 +4292,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Diese Kraft knnen selbst die Gtter nicht mehr mchtiger machen." + "$unit($unit) in $region($region): '$order($command)' - Diese Kraft können selbst die Götter nicht mehr mächtiger machen." "$unit($unit) in $region($region): '$order($command)' - Even the gods cannot improve this power." @@ -4298,7 +4319,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Partei mu mindestens 10 Runden alt sein." + "$unit($unit) in $region($region): '$order($command)' - Die Partei muß mindestens 10 Runden alt sein." "$unit($unit) in $region($region): '$order($command)' - The faction has to be 10 turns old." @@ -4316,7 +4337,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Das Gebude hat schon einen Namen." + "$unit($unit) in $region($region): '$order($command)' - Das Gebäude hat schon einen Namen." "$unit($unit) in $region($region): '$order($command)' - The building is already named." @@ -4343,7 +4364,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Keine gltige Rasse angegeben." + "$unit($unit) in $region($region): '$order($command)' - Keine gültige Rasse angegeben." "$unit($unit) in $region($region): '$order($command)' - You did not specify a valid race." @@ -4352,7 +4373,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Einheit mu sich an Land befinden." + "$unit($unit) in $region($region): '$order($command)' - Die Einheit muß sich an Land befinden." "$unit($unit) in $region($region): '$order($command)' - The unit must be on land." @@ -4385,7 +4406,7 @@ - "$unit($unit) in $region($region): '$order($command)' - In $region($target) sind keine Grber." + "$unit($unit) in $region($region): '$order($command)' - In $region($target) sind keine Gräber." "$unit($unit) in $region($region): '$order($command)' - There are no graves in $region($target)." @@ -4394,7 +4415,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Partei mu mindestens 81 Wochen alt sein, um einen Neustart mit einer anderen Rasse zu versuchen." + "$unit($unit) in $region($region): '$order($command)' - Die Partei muß mindestens 81 Wochen alt sein, um einen Neustart mit einer anderen Rasse zu versuchen." "$unit($unit) in $region($region): '$order($command)' - The faction must be at least 81 weeks old to restart with a new race." @@ -4421,7 +4442,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Hier knnen nur Orks rekrutiert werden." + "$unit($unit) in $region($region): '$order($command)' - Hier können nur Orks rekrutiert werden." "$unit($unit) in $region($region): '$order($command)' - You can recruit only orcs here." @@ -4439,7 +4460,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Das Gebude ist noch nicht fertig gebaut." + "$unit($unit) in $region($region): '$order($command)' - Das Gebäude ist noch nicht fertig gebaut." "$unit($unit) in $region($region): '$order($command)' - The building is not finished yet." @@ -4448,7 +4469,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Fr das Gebude wurde noch kein Unterhalt bezahlt." + "$unit($unit) in $region($region): '$order($command)' - Für das Gebäude wurde noch kein Unterhalt bezahlt." "$unit($unit) in $region($region): '$order($command)' - Maintenance has not been paid yet." @@ -4457,7 +4478,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Einheit ist mit Ausschiffen beschftigt.." + "$unit($unit) in $region($region): '$order($command)' - Die Einheit ist mit Ausschiffen beschäftigt.." "$unit($unit) in $region($region): '$order($command)' - The unit is busy disembarking." @@ -4475,7 +4496,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Dieser Typ Einheit kann keine Gebude betreten." + "$unit($unit) in $region($region): '$order($command)' - Dieser Typ Einheit kann keine Gebäude betreten." "$unit($unit) in $region($region): '$order($command)' - This type of unit cannot enter a building." @@ -4484,7 +4505,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Einheit oder ihre Tiere wrden dort nicht berleben." + "$unit($unit) in $region($region): '$order($command)' - Die Einheit oder ihre Tiere würden dort nicht überleben." "$unit($unit) in $region($region): '$order($command)' - The unit or its animals would not survive there." @@ -4531,7 +4552,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Nur normale Personen knnen Steuern eintreiben." + "$unit($unit) in $region($region): '$order($command)' - Nur normale Personen können Steuern eintreiben." "$unit($unit) in $region($region): '$order($command)' - Only normal characters can collect taxes." @@ -4540,7 +4561,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Dafr braucht ein Einheit mindestens Kruterkunde 7." + "$unit($unit) in $region($region): '$order($command)' - Dafür braucht ein Einheit mindestens Kräuterkunde 7." "$unit($unit) in $region($region): '$order($command)' - A herbalism skill of 7 or higher is required." @@ -4549,7 +4570,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Einheiten in den hinteren Reihen knnen nicht angreifen." + "$unit($unit) in $region($region): '$order($command)' - Einheiten in den hinteren Reihen können nicht angreifen." "$unit($unit) in $region($region): '$order($command)' - Units from the backmost rows cannot attack." @@ -4567,7 +4588,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Einheit ist nicht bewaffnet und kampffhig." + "$unit($unit) in $region($region): '$order($command)' - Die Einheit ist nicht bewaffnet und kampffähig." "$unit($unit) in $region($region): '$order($command)' - The unit is not armed and ready to fight." @@ -4586,7 +4607,7 @@ - "$unit($unit) in $region($region): '$order($command)' - $race($race,0) knnen nicht arbeiten." + "$unit($unit) in $region($region): '$order($command)' - $race($race,0) können nicht arbeiten." "$unit($unit) in $region($region): '$order($command)' - $race($race,0) cannot work." @@ -4595,7 +4616,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Hungernde Soldaten kmpfen nicht." + "$unit($unit) in $region($region): '$order($command)' - Hungernde Soldaten kämpfen nicht." "$unit($unit) in $region($region): '$order($command)' - Starving units do not fight." @@ -4604,7 +4625,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Hungernde Einheiten knnen nicht zaubern." + "$unit($unit) in $region($region): '$order($command)' - Hungernde Einheiten können nicht zaubern." "$unit($unit) in $region($region): '$order($command)' - Starving units cannot cast spells." @@ -4613,7 +4634,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Hungernde Einheiten knnen nicht bewachen." + "$unit($unit) in $region($region): '$order($command)' - Hungernde Einheiten können nicht bewachen." "$unit($unit) in $region($region): '$order($command)' - Starving units cannot guard." @@ -4721,7 +4742,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Es ist zu gefhrlich, ein sturmgepeitschtes Schiff fliegen zu lassen." + "$unit($unit) in $region($region): '$order($command)' - Es ist zu gefährlich, ein sturmgepeitschtes Schiff fliegen zu lassen." "$unit($unit) in $region($region): '$order($command)' - It is too dangerous to fly the ship in the storm." @@ -4748,7 +4769,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Zu dieser Einheit kann keine Aura bertragen werden." + "$unit($unit) in $region($region): '$order($command)' - Zu dieser Einheit kann keine Aura übertragen werden." "$unit($unit) in $region($region): '$order($command)' - You cannot transfer aura to this unit." @@ -4757,7 +4778,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Auf dem Gebude liegt bereits so ein Zauber." + "$unit($unit) in $region($region): '$order($command)' - Auf dem Gebäude liegt bereits so ein Zauber." "$unit($unit) in $region($region): '$order($command)' - There is alrady a spell on that building." @@ -4809,7 +4830,7 @@ - "$unit($unit) in $region($region): '$order($command)' - $unit($target) wusste trotz intensivem Verhr nichts ber $region($tregion) zu berichten." + "$unit($unit) in $region($region): '$order($command)' - $unit($target) wusste trotz intensivem Verhör nichts über $region($tregion) zu berichten." "$unit($unit) in $region($region): '$order($command)' - Despite intense questioning, $unit($target) did not have anything to tell about $region($tregion)." @@ -4819,7 +4840,7 @@ - "$unit($unit) in $region($region): '$order($command)' - So viele Persoenen bersteigen die Krfte des Magiers." + "$unit($unit) in $region($region): '$order($command)' - So viele Persoenen übersteigen die Kräfte des Magiers." "$unit($unit) in $region($region): '$order($command)' - This many people exceed the powers of the magician." @@ -4830,7 +4851,7 @@ - "$unit($unit) in $region($region): '$order($command)' - $unit($target) hat unaufkndbare Bindungen an seine alte Partei." + "$unit($unit) in $region($region): '$order($command)' - $unit($target) hat unaufkündbare Bindungen an seine alte Partei." "$unit($unit) in $region($region): '$order($command)' - $unit($target) have unbreakable commitments to their faction." @@ -4849,7 +4870,7 @@ - "$unit($unit) in $region($region): '$order($command)' - In einer Region ohne Bume kann man diesen Zauber nicht wirken." + "$unit($unit) in $region($region): '$order($command)' - In einer Region ohne Bäume kann man diesen Zauber nicht wirken." "$unit($unit) in $region($region): '$order($command)' - You cannot cast this spell in a region without trees." @@ -4867,7 +4888,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Das ist keine gltige Rasse." + "$unit($unit) in $region($region): '$order($command)' - Das ist keine gültige Rasse." "$unit($unit) in $region($region): '$order($command)' - This is not a valid race." @@ -4885,7 +4906,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die maximale Aura reicht nicht fr diesen Zauber." + "$unit($unit) in $region($region): '$order($command)' - Die maximale Aura reicht nicht für diesen Zauber." "$unit($unit) in $region($region): '$order($command)' - Magician's maximum aura is not high enough for this spell." @@ -4912,7 +4933,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Um einen Heimstein zu erschaffen, mu der Zauberer in einer Burg sein." + "$unit($unit) in $region($region): '$order($command)' - Um einen Heimstein zu erschaffen, muß der Zauberer in einer Burg sein." "$unit($unit) in $region($region): '$order($command)' - The magician has to be in a castle to create a homestone." @@ -4930,7 +4951,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Dorthin fhrt kein Weg." + "$unit($unit) in $region($region): '$order($command)' - Dorthin führt kein Weg." "$unit($unit) in $region($region): '$order($command)' - There is no route leading there." @@ -4957,7 +4978,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Wege zwischen Geisterwelt und Realitt scheinen blockiert zu sein." + "$unit($unit) in $region($region): '$order($command)' - Die Wege zwischen Geisterwelt und Realität scheinen blockiert zu sein." "$unit($unit) in $region($region): '$order($command)' - The paths to the spirit world seem to be blocked." @@ -4966,7 +4987,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Der Zauber funktioniert nur in Wldern." + "$unit($unit) in $region($region): '$order($command)' - Der Zauber funktioniert nur in Wäldern." "$unit($unit) in $region($region): '$order($command)' - This spell works only in forests." @@ -4984,7 +5005,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Selbst der mchtigste Magier der Welt knnte keinen Ozean austrocknen lassen." + "$unit($unit) in $region($region): '$order($command)' - Selbst der mächtigste Magier der Welt könnte keinen Ozean austrocknen lassen." "$unit($unit) in $region($region): '$order($command)' - Even the gods cannot dry out an entire ocean." @@ -5011,7 +5032,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Der Zauber scheint ungewhnlich schwach zu sein. Irgendetwas hat die magischen Energien abgeleitet." + "$unit($unit) in $region($region): '$order($command)' - Der Zauber scheint ungewöhnlich schwach zu sein. Irgendetwas hat die magischen Energien abgeleitet." "$unit($unit) in $region($region): '$order($command)' - The spell seems exceptionally weak. Something has interfred with the magical energies." @@ -5020,7 +5041,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Einheit kann den Befehl in dieser Runde nicht ausfhren, da sie sich bewegt hat." + "$unit($unit) in $region($region): '$order($command)' - Die Einheit kann den Befehl in dieser Runde nicht ausführen, da sie sich bewegt hat." "$unit($unit) in $region($region): '$order($command)' - The unit cannot execute this command because it has moved." @@ -5056,7 +5077,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Dazu mu sich der Magier in der Burg oder an Bord des Schiffes befinden." + "$unit($unit) in $region($region): '$order($command)' - Dazu muß sich der Magier in der Burg oder an Bord des Schiffes befinden." "$unit($unit) in $region($region): '$order($command)' - To do this, the magician has to be in a castle or on board a ship." @@ -5065,7 +5086,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Der Zauber schlgt fehl." + "$unit($unit) in $region($region): '$order($command)' - Der Zauber schlägt fehl." "$unit($unit) in $region($region): '$order($command)' - The spell fails." @@ -5155,7 +5176,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Bauern nehmen dieses grozgige Geschenk nicht an." + "$unit($unit) in $region($region): '$order($command)' - Die Bauern nehmen dieses großzügige Geschenk nicht an." "$unit($unit) in $region($region): '$order($command)' - The peasants did not accept this gracious gift." @@ -5173,7 +5194,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Es konnten keine Luxusgter verkauft werden." + "$unit($unit) in $region($region): '$order($command)' - Es konnten keine Luxusgüter verkauft werden." "$unit($unit) in $region($region): '$order($command)' - No luxury items could be sold." @@ -5209,7 +5230,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Nestwrme kann nur von Insektenvlkern benutzt werden." + "$unit($unit) in $region($region): '$order($command)' - Die Nestwärme kann nur von Insektenvölkern benutzt werden." "$unit($unit) in $region($region): '$order($command)' - This potion can only be used by insects." @@ -5236,7 +5257,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Es konnten keine Luxusgter gekauft werden." + "$unit($unit) in $region($region): '$order($command)' - Es konnten keine Luxusgüter gekauft werden." "$unit($unit) in $region($region): '$order($command)' - No luxury items could be bought." @@ -5245,7 +5266,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Es konnten keine Personen bergeben werden." + "$unit($unit) in $region($region): '$order($command)' - Es konnten keine Personen übergeben werden." "$unit($unit) in $region($region): '$order($command)' - No person could be handed over." @@ -5254,7 +5275,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Magier arbeiten grundstzlich nur alleine!" + "$unit($unit) in $region($region): '$order($command)' - Magier arbeiten grundsätzlich nur alleine!" "$unit($unit) in $region($region): '$order($command)' - Magicians always work alone!" @@ -5290,7 +5311,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Hochqualifizierte Personen weigern sich, fr andere Parteien zu arbeiten." + "$unit($unit) in $region($region): '$order($command)' - Hochqualifizierte Personen weigern sich, für andere Parteien zu arbeiten." "$unit($unit) in $region($region): '$order($command)' - Highly qualified people refuse to work for other parties." @@ -5299,7 +5320,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Einheit schliet sich den Bauern an." + "$unit($unit) in $region($region): '$order($command)' - Die Einheit schließt sich den Bauern an." "$unit($unit) in $region($region): '$order($command)' - The unit joins the local peasants." @@ -5308,7 +5329,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Einheit springt ber Bord und ertrinkt." + "$unit($unit) in $region($region): '$order($command)' - Die Einheit springt über Bord und ertrinkt." "$unit($unit) in $region($region): '$order($command)' - The unit jumps over board and drowns." @@ -5344,7 +5365,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Zum Straenbau braucht man Steine." + "$unit($unit) in $region($region): '$order($command)' - Zum Straßenbau braucht man Steine." "$unit($unit) in $region($region): '$order($command)' - You need stones to build a road." @@ -5371,7 +5392,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Einheit ist nicht Burgherr der grten Burg in der Region." + "$unit($unit) in $region($region): '$order($command)' - Die Einheit ist nicht Burgherr der größten Burg in der Region." "$unit($unit) in $region($region): '$order($command)' - The unit is not in command of the largest castle in the region." @@ -5380,7 +5401,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Einheit ist nicht der Kapitn des Schiffes." + "$unit($unit) in $region($region): '$order($command)' - Die Einheit ist nicht der Kapitän des Schiffes." "$unit($unit) in $region($region): '$order($command)' - The unit is not captain of a ship." @@ -5425,7 +5446,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Einheit hat nicht mehr genug Kristalle fr so viele Personen." + "$unit($unit) in $region($region): '$order($command)' - Die Einheit hat nicht mehr genug Kristalle für so viele Personen." "$unit($unit) in $region($region): '$order($command)' - The unit does not have enough crystals left for this many people." @@ -5443,7 +5464,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Unterschiedliche Typen knnen nicht gemischt werden." + "$unit($unit) in $region($region): '$order($command)' - Unterschiedliche Typen können nicht gemischt werden." "$unit($unit) in $region($region): '$order($command)' - Different types do not mix." @@ -5452,7 +5473,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Uns gehrt nichts, was man abreien oder versenken knnte." + "$unit($unit) in $region($region): '$order($command)' - Uns gehört nichts, was man abreißen oder versenken könnte." "$unit($unit) in $region($region): '$order($command)' - We do not have anything that could be demolished." @@ -5479,7 +5500,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Um in Wsten Straen bauen zu knnen, mu zuerst eine Karawanserei errichtet werden." + "$unit($unit) in $region($region): '$order($command)' - Um in Wüsten Straßen bauen zu können, muß zuerst eine Karawanserei errichtet werden." "$unit($unit) in $region($region): '$order($command)' - You must build a caravansary before building roads through deserts." @@ -5488,7 +5509,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Um in Smpfen Straen bauen zu knnen, mu zuerst ein Damm errichtet werden." + "$unit($unit) in $region($region): '$order($command)' - Um in Sümpfen Straßen bauen zu können, muß zuerst ein Damm errichtet werden." "$unit($unit) in $region($region): '$order($command)' - You must build a dam before building roads through swamps." @@ -5560,7 +5581,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Pferde kann man nur in einer Pferdezucht zchten." + "$unit($unit) in $region($region): '$order($command)' - Pferde kann man nur in einer Pferdezucht züchten." "$unit($unit) in $region($region): '$order($command)' - You can only breed horses in a stable." @@ -5578,7 +5599,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Personen knnen nur an Menschen bergeben werden." + "$unit($unit) in $region($region): '$order($command)' - Personen können nur an Menschen übergeben werden." "$unit($unit) in $region($region): '$order($command)' - Characters can be given only to human parties." @@ -5596,7 +5617,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Nur Elfen knnen diese Bgen herstellen." + "$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." @@ -5632,7 +5653,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Nummer ist nicht im gltigen Bereich." + "$unit($unit) in $region($region): '$order($command)' - Nummer ist nicht im gültigen Bereich." "$unit($unit) in $region($region): '$order($command)' - Number is not valid." @@ -5641,7 +5662,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Nichts angegeben, was wir bergeben sollen." + "$unit($unit) in $region($region): '$order($command)' - Nichts angegeben, was wir übergeben sollen." "$unit($unit) in $region($region): '$order($command)' - Item to be handed over was not supplied." @@ -5650,7 +5671,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Namen drfen keine Klammern enthalten." + "$unit($unit) in $region($region): '$order($command)' - Namen dürfen keine Klammern enthalten." "$unit($unit) in $region($region): '$order($command)' - Names may not contain parenthesis." @@ -5659,7 +5680,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Nachricht zu lang - gekrzt." + "$unit($unit) in $region($region): '$order($command)' - Nachricht zu lang - gekürzt." "$unit($unit) in $region($region): '$order($command)' - Message has been cut (too long)." @@ -5668,7 +5689,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Man mu angeben, ob eine Burg, ein Schiff, eine Region oder eine Einheit beschrieben werden soll." + "$unit($unit) in $region($region): '$order($command)' - Man muß angeben, ob eine Burg, ein Schiff, eine Region oder eine Einheit beschrieben werden soll." "$unit($unit) in $region($region): '$order($command)' - Specify if description is for a castle, a ship, a region, or a unit." @@ -5677,7 +5698,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Man mu angeben, ob eine Burg, ein Schiff, eine Einheit, eine Region oder eine Partei benannt werden soll." + "$unit($unit) in $region($region): '$order($command)' - Man muß angeben, ob eine Burg, ein Schiff, eine Einheit, eine Region oder eine Partei benannt werden soll." "$unit($unit) in $region($region): '$order($command)' - Specify if a castle, a ship, a region, or a unit is supposed to be named." @@ -5686,7 +5707,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Es sind keine Kruter zu finden." + "$unit($unit) in $region($region): '$order($command)' - Es sind keine Kräuter zu finden." "$unit($unit) in $region($region): '$order($command)' - No herbs could be found." @@ -5695,7 +5716,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Man braucht mindestens zwei Pferde, um sie zu zchten." + "$unit($unit) in $region($region): '$order($command)' - Man braucht mindestens zwei Pferde, um sie zu züchten." "$unit($unit) in $region($region): '$order($command)' - You need at least two horses to breed more." @@ -5704,7 +5725,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Magier mssen zum studieren allein sein." + "$unit($unit) in $region($region): '$order($command)' - Magier müssen zum studieren allein sein." "$unit($unit) in $region($region): '$order($command)' - When studying, magicians need to be alone." @@ -5713,7 +5734,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Leere Einheiten knnen nicht bergeben werden." + "$unit($unit) in $region($region): '$order($command)' - Leere Einheiten können nicht übergeben werden." "$unit($unit) in $region($region): '$order($command)' - Empty units can not be handed over." @@ -5731,7 +5752,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Keiner hier kann Straen bauen." + "$unit($unit) in $region($region): '$order($command)' - Keiner hier kann Straßen bauen." "$unit($unit) in $region($region): '$order($command)' - Nobody here can build roads." @@ -5740,7 +5761,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Einheit kann keine weiteren Gter handeln." + "$unit($unit) in $region($region): '$order($command)' - Die Einheit kann keine weiteren Güter handeln." "$unit($unit) in $region($region): '$order($command)' - The unit cannot trade any more goods." @@ -5749,7 +5770,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Keiner hier kann ein Gebude errichten." + "$unit($unit) in $region($region): '$order($command)' - Keiner hier kann ein Gebäude errichten." "$unit($unit) in $region($region): '$order($command)' - Nobody here can construct a building." @@ -5776,7 +5797,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Insekten knnen im Winter nur in Wsten rekrutiert werden." + "$unit($unit) in $region($region): '$order($command)' - Insekten können im Winter nur in Wüsten rekrutiert werden." "$unit($unit) in $region($region): '$order($command)' - In winter, insects can be recruited only in deserts." @@ -5785,7 +5806,7 @@ - "$unit($unit) in $region($region): '$order($command)' - In Gletschern knnen keine Insekten rekrutiert werden." + "$unit($unit) in $region($region): '$order($command)' - In Gletschern können keine Insekten rekrutiert werden." "$unit($unit) in $region($region): '$order($command)' - Insects cannot be recruited in glacier regions." @@ -5794,7 +5815,7 @@ - "$unit($unit) in $region($region): '$order($command)' - In dieser Einheit gibt es niemanden, den man transferieren knnte." + "$unit($unit) in $region($region): '$order($command)' - In dieser Einheit gibt es niemanden, den man transferieren könnte." "$unit($unit) in $region($region): '$order($command)' - Nobody in this unit can be transferred." @@ -5803,7 +5824,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Illusionen knnen eine Region nicht bewachen." + "$unit($unit) in $region($region): '$order($command)' - Illusionen können eine Region nicht bewachen." "$unit($unit) in $region($region): '$order($command)' - Illusions cannot guard a region." @@ -5812,7 +5833,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Hier kann man keine Strae bauen." + "$unit($unit) in $region($region): '$order($command)' - Hier kann man keine Straße bauen." "$unit($unit) in $region($region): '$order($command)' - You cannot build a road here." @@ -5848,7 +5869,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Hier gibt es keine Mallornbume." + "$unit($unit) in $region($region): '$order($command)' - Hier gibt es keine Mallornbäume." "$unit($unit) in $region($region): '$order($command)' - There are no mallorn trees here." @@ -5857,7 +5878,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Einheit fhrt nicht mit uns." + "$unit($unit) in $region($region): '$order($command)' - Die Einheit fährt nicht mit uns." "$unit($unit) in $region($region): '$order($command)' - The unit does not have travel with us." @@ -5875,7 +5896,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Einheit hat nicht gengend Materialien fr den Schiffbau." + "$unit($unit) in $region($region): '$order($command)' - Die Einheit hat nicht genügend Materialien für den Schiffbau." "$unit($unit) in $region($region): '$order($command)' - The unit is lacking materials for building the ship." @@ -5884,7 +5905,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Fr das Elixier bentigt man Drachenblut." + "$unit($unit) in $region($region): '$order($command)' - Für das Elixier benötigt man Drachenblut." "$unit($unit) in $region($region): '$order($command)' - Dragon blood is required for this elixir." @@ -5938,7 +5959,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Einheit mu zuerst die Region bewachen." + "$unit($unit) in $region($region): '$order($command)' - Einheit muß zuerst die Region bewachen." "$unit($unit) in $region($region): '$order($command)' - The unit must first guard the region." @@ -5947,7 +5968,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Einheit ist nicht bewaffnet und kampffhig." + "$unit($unit) in $region($region): '$order($command)' - Einheit ist nicht bewaffnet und kampffähig." "$unit($unit) in $region($region): '$order($command)' - The unit is not armed and ready to fight." @@ -5956,7 +5977,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Ein Schiff oder eine Burg mu angegeben werden." + "$unit($unit) in $region($region): '$order($command)' - Ein Schiff oder eine Burg muß angegeben werden." "$unit($unit) in $region($region): '$order($command)' - A ship or a castle must be supplied." @@ -5965,7 +5986,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Ein Fluch verhindert die bergabe." + "$unit($unit) in $region($region): '$order($command)' - Ein Fluch verhindert die Übergabe." "$unit($unit) in $region($region): '$order($command)' - A curse prevented the transfer from happening." @@ -6108,7 +6129,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Pferde wrden ertrinken." + "$unit($unit) in $region($region): '$order($command)' - Die Pferde würden ertrinken." "$unit($unit) in $region($region): '$order($command)' - The horses would drown." @@ -6126,7 +6147,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Lernkosten knnen nicht bezahlt werden." + "$unit($unit) in $region($region): '$order($command)' - Die Lernkosten können nicht bezahlt werden." "$unit($unit) in $region($region): '$order($command)' - Tuition was too high to be paid." @@ -6173,7 +6194,7 @@ - "$unit($mage) horcht $unit($unit) ber $region($tregion) aus." + "$unit($mage) horcht $unit($unit) über $region($tregion) aus." "$unit($mage) questions $unit($unit) about $region($tregion)." @@ -6182,7 +6203,7 @@ - "$unit($mage) verschafft $unit($unit) einige feuchtfrhliche Stunden mit heftigen Nachwirkungen." + "$unit($mage) verschafft $unit($unit) einige feuchtfröhliche Stunden mit heftigen Nachwirkungen." "$unit($mage) invites $unit($unit) for a few too many drinks and a massive hangover." @@ -6190,7 +6211,7 @@ - "$unit($unit) hat hllische Kopfschmerzen und kann sich an die vergangene Woche nicht mehr erinnern. Nur noch daran, wie alles mit einer frhlichen Feier in irgendeiner Taverne anfing...." + "$unit($unit) hat höllische Kopfschmerzen und kann sich an die vergangene Woche nicht mehr erinnern. Nur noch daran, wie alles mit einer fröhlichen Feier in irgendeiner Taverne anfing...." "$unit($unit) has a splitting headache and can hardly remember last week. Except that it all started in the tavern..." @@ -6199,7 +6220,7 @@ - "$unit($mage) besnftigt $unit($unit)." + "$unit($mage) besänftigt $unit($unit)." "$unit($mage) calms $unit($unit)." @@ -6207,7 +6228,7 @@ - "$unit($unit) verfiel dem Glcksspiel und hat fast sein ganzes Hab und gut verspielt." + "$unit($unit) verfiel dem Glücksspiel und hat fast sein ganzes Hab und gut verspielt." "$unit($unit) gambles for high stakes and loses almost everything." @@ -6227,7 +6248,7 @@ - "$unit($mage) lt $unit($target) als $race($race,$unit.size($target)) erscheinen." + "$unit($mage) läßt $unit($target) als $race($race,$unit.size($target)) erscheinen." "$unit($mage) makes $unit($target) appear as $race($race,$unit.size($target))." @@ -6235,7 +6256,7 @@ - "$unit($unit) wird kurz von einem magischen Licht umhllt." + "$unit($unit) wird kurz von einem magischen Licht umhüllt." "$unit($unit) is briefly surrounded by a magical light." @@ -6251,7 +6272,7 @@ - "$unit($unit) beschwrt einen magischen Wind, der die Schiffe ber das Wasser treibt." + "$unit($unit) beschwört einen magischen Wind, der die Schiffe über das Wasser treibt." "$unit($unit) calls up a magical storm that whips the ship over the waters." @@ -6260,7 +6281,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Einheit wei nichts ber Botanik." + "$unit($unit) in $region($region): '$order($command)' - Die Einheit weiß nichts über Botanik." "$unit($unit) in $region($region): '$order($command)' - The unit does not know anything about herbalism." @@ -6269,7 +6290,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Einheit wei nicht, wie man gaukelt." + "$unit($unit) in $region($region): '$order($command)' - Die Einheit weiß nicht, wie man gaukelt." "$unit($unit) in $region($region): '$order($command)' - The unit does not know how to entertain." @@ -6278,7 +6299,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Einheit trgt zuviel Gewicht, um sich bewegen zu knnen." + "$unit($unit) in $region($region): '$order($command)' - Die Einheit trägt zuviel Gewicht, um sich bewegen zu können." "$unit($unit) in $region($region): '$order($command)' - The unit is too heavily loaded to move." @@ -6287,7 +6308,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Einheit kann soviele Pferde nicht bndigen." + "$unit($unit) in $region($region): '$order($command)' - Die Einheit kann soviele Pferde nicht bändigen." "$unit($unit) in $region($region): '$order($command)' - The unit cannot tame that many horses." @@ -6314,7 +6335,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Einheit kann keine Trnke herstellen." + "$unit($unit) in $region($region): '$order($command)' - Die Einheit kann keine Tränke herstellen." "$unit($unit) in $region($region): '$order($command)' - The unit cannot make potions." @@ -6323,7 +6344,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Einheit kann keine weiteren langen Befehle ausfhren." + "$unit($unit) in $region($region): '$order($command)' - Die Einheit kann keine weiteren langen Befehle ausführen." "$unit($unit) in $region($region): '$order($command)' - The unit cannot execute more long orders." @@ -6341,7 +6362,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Einheit ist nicht erfahren genug dafr." + "$unit($unit) in $region($region): '$order($command)' - Die Einheit ist nicht erfahren genug dafür." "$unit($unit) in $region($region): '$order($command)' - The unit is not experienced enough to do this." @@ -6350,7 +6371,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Einheit ist nicht der Eigentmer." + "$unit($unit) in $region($region): '$order($command)' - Die Einheit ist nicht der Eigentümer." "$unit($unit) in $region($region): '$order($command)' - The unit is not the owner." @@ -6359,7 +6380,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Einheit ist nicht bewaffnet und kampffhig." + "$unit($unit) in $region($region): '$order($command)' - Die Einheit ist nicht bewaffnet und kampffähig." "$unit($unit) in $region($region): '$order($command)' - The unit is not armed and ready to fight." @@ -6449,7 +6470,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Einheit hat keine Kruter." + "$unit($unit) in $region($region): '$order($command)' - Die Einheit hat keine Kräuter." "$unit($unit) in $region($region): '$order($command)' - The unit does not have any herbs." @@ -6478,7 +6499,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Einheit hat diesen Gegenstand zwar, aber smtliche $int($reservation) $resource($resource,$reservation) sind reserviert." + "$unit($unit) in $region($region): '$order($command)' - Die Einheit hat diesen Gegenstand zwar, aber sämtliche $int($reservation) $resource($resource,$reservation) sind reserviert." "$unit($unit) in $region($region): '$order($command)' - The unit has this item, but all $int($reservation) $resource($resource,$reservation) are reserved." @@ -6487,7 +6508,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Einheit hat diese Kruter nicht." + "$unit($unit) in $region($region): '$order($command)' - Die Einheit hat diese Kräuter nicht." "$unit($unit) in $region($region): '$order($command)' - The unit does not have these herbs." @@ -6497,7 +6518,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Einheiten drfen nicht mehr als $int($maxsize) Personen enthalten." + "$unit($unit) in $region($region): '$order($command)' - Einheiten dürfen nicht mehr als $int($maxsize) Personen enthalten." "$unit($unit) in $region($region): '$order($command)' - Units may not have more than $int($maxsize) members." @@ -6506,7 +6527,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Einheit darf nicht an Bord kommen, da sie das Schiff berladen wrde." + "$unit($unit) in $region($region): '$order($command)' - Die Einheit darf nicht an Bord kommen, da sie das Schiff überladen würde." "$unit($unit) in $region($region): '$order($command)' - The unit cannot go aboard, the ship would be overloaded." @@ -6551,7 +6572,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Botschaft enthlt keinen Text." + "$unit($unit) in $region($region): '$order($command)' - Die Botschaft enthält keinen Text." "$unit($unit) in $region($region): '$order($command)' - The message does not contain text." @@ -6596,7 +6617,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Der Belagerungszustand macht Spionage unmglich." + "$unit($unit) in $region($region): '$order($command)' - Der Belagerungszustand macht Spionage unmöglich." "$unit($unit) in $region($region): '$order($command)' - Espionage was not possible due to siege." @@ -6605,7 +6626,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Der Belagerungszustand macht die Kontaktaufnahme unmglich." + "$unit($unit) in $region($region): '$order($command)' - Der Belagerungszustand macht die Kontaktaufnahme unmöglich." "$unit($unit) in $region($region): '$order($command)' - Contact was not possible due to siege." @@ -6641,7 +6662,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Das Schiff mu erst verlassen werden." + "$unit($unit) in $region($region): '$order($command)' - Das Schiff muß erst verlassen werden." "$unit($unit) in $region($region): '$order($command)' - First you have to leave the ship." @@ -6660,7 +6681,7 @@ - "$unit($unit) in $region($region): '$order($command)' - $ship($ship) ist zu gro, um fliegen zu knnen." + "$unit($unit) in $region($region): '$order($command)' - $ship($ship) ist zu groß, um fliegen zu können." "$unit($unit) in $region($region): '$order($command)' - $ship($ship) is too bulky to fly." @@ -6705,7 +6726,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Der Besitzer muss das Gebude zuerst verlassen." + "$unit($unit) in $region($region): '$order($command)' - Der Besitzer muss das Gebäude zuerst verlassen." "$unit($unit) in $region($region): '$order($command)' - The owner must first LEAVE the building." @@ -6714,7 +6735,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Das Schiff gehrt uns nicht." + "$unit($unit) in $region($region): '$order($command)' - Das Schiff gehört uns nicht." "$unit($unit) in $region($region): '$order($command)' - The ship is not ours." @@ -6723,7 +6744,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Das Gebude gehrt uns nicht." + "$unit($unit) in $region($region): '$order($command)' - Das Gebäude gehört uns nicht." "$unit($unit) in $region($region): '$order($command)' - The building is not ours." @@ -6777,7 +6798,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Das Gebude wurde nicht gefunden." + "$unit($unit) in $region($region): '$order($command)' - Das Gebäude wurde nicht gefunden." "$unit($unit) in $region($region): '$order($command)' - Building could not be found." @@ -6786,7 +6807,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Das Gebude gehrt uns nicht." + "$unit($unit) in $region($region): '$order($command)' - Das Gebäude gehört uns nicht." "$unit($unit) in $region($region): '$order($command)' - The building is not ours." @@ -6795,7 +6816,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Das Gebude ist bereits fertig." + "$unit($unit) in $region($region): '$order($command)' - Das Gebäude ist bereits fertig." "$unit($unit) in $region($region): '$order($command)' - The building is already completed." @@ -6813,7 +6834,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Beschreibung zu lang - gekrzt." + "$unit($unit) in $region($region): '$order($command)' - Beschreibung zu lang - gekürzt." "$unit($unit) in $region($region): '$order($command)' - Description has been cut (too long)." @@ -6859,7 +6880,7 @@ - "$unit($unit) in $region($region): '$order($command)' - $resource($item,0) knnen nur von Ein-Personen Einheiten benutzt werden." + "$unit($unit) in $region($region): '$order($command)' - $resource($item,0) können nur von Ein-Personen Einheiten benutzt werden." "$unit($unit) in $region($region): '$order($command)' - $resource($item,0) can only be used by single-person units." @@ -6868,7 +6889,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Einheit ist noch zu erschpft vom Einmarsch um zu attackieren." + "$unit($unit) in $region($region): '$order($command)' - Die Einheit ist noch zu erschöpft vom Einmarsch um zu attackieren." "'$order($command)' - $unit($unit) marched into $region($region) during the last turn and is too exhausted to attack." @@ -6888,7 +6909,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Einheit steht nicht im bentigten Gebude, $localize($building)." + "$unit($unit) in $region($region): '$order($command)' - Die Einheit steht nicht im benötigten Gebäude, $localize($building)." "$unit($unit) in $region($region): '$order($command)' - The unit must be in a $localize($building) to produce this." @@ -6910,7 +6931,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Man bentigt mindestens $int($minskill) $skill($skill), um $resource($product,0) zu pflanzen." + "$unit($unit) in $region($region): '$order($command)' - Man benötigt mindestens $int($minskill) $skill($skill), um $resource($product,0) zu pflanzen." "$unit($unit) in $region($region): '$order($command)' - At least $skill($skill) $int($minskill) is needed for planting $resource($product,0)." @@ -6922,7 +6943,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Man bentigt mindestens $int($minskill) $skill($skill), um $resource($product,0) zu produzieren." + "$unit($unit) in $region($region): '$order($command)' - Man benötigt mindestens $int($minskill) $skill($skill), um $resource($product,0) zu produzieren." "$unit($unit) in $region($region): '$order($command)' - You need at least $int($minskill) $skill($skill), to produce $resource($product,0)." @@ -6952,7 +6973,7 @@ - "$unit($unit) bergibt $int($amount) Person$if($eq($amount,1),"","en") an $unit($target)." + "$unit($unit) übergibt $int($amount) Person$if($eq($amount,1),"","en") an $unit($target)." "$unit($unit) transfers $int($amount) person$if($eq($amount,1),"","s") to $unit($target)." @@ -6963,7 +6984,7 @@ - "$unit($unit) bergibt $int($amount) $resource($resource,$amount) an $unit($target)." + "$unit($unit) übergibt $int($amount) $resource($resource,$amount) an $unit($target)." "$unit($unit) gives $int($amount) $resource($resource,$amount) to $unit($target)." @@ -6974,7 +6995,7 @@ - "$unit($target) erhlt $int($amount) $resource($resource,$amount) von $unit($unit)." + "$unit($target) erhält $int($amount) $resource($resource,$amount) von $unit($unit)." "$unit($target) receives $int($amount) $resource($resource,$amount) from $unit($unit)." @@ -6983,7 +7004,7 @@ - "$unit($unit) ertrnkt $int($amount) Person$if($eq($amount,1),"","en")." + "$unit($unit) ertränkt $int($amount) Person$if($eq($amount,1),"","en")." "$unit($unit) drowns $int($amount)." @@ -6992,7 +7013,7 @@ - "$unit($unit) bergibt $int($amount) Person$if($eq($amount,1),"","en") an die Bauern." + "$unit($unit) übergibt $int($amount) Person$if($eq($amount,1),"","en") an die Bauern." "$unit($unit) transfers $int($amount) person$if($eq($amount,1),"","s") to the local peasants." @@ -7002,7 +7023,7 @@ - "$unit($unit) bergibt $int($amount) $resource($resource,$amount) an die Bauern." + "$unit($unit) übergibt $int($amount) $resource($resource,$amount) an die Bauern." "$unit($unit) gives $int($amount) $resource($resource,$amount) to the local peasants." @@ -7020,7 +7041,7 @@ - "$unit($unit) fehlen $resource($item,0) fr den Betrieb von $building($building)." + "$unit($unit) fehlen $resource($item,0) für den Betrieb von $building($building)." "$unit($unit) lacks $resource($item,0) to operate $building($building)." @@ -7035,14 +7056,14 @@ - "Der Unterhalt von $building($building) konnte nicht gezahlt werden, das Gebude war diese Woche nicht funktionstchtig." + "Der Unterhalt von $building($building) konnte nicht gezahlt werden, das Gebäude war diese Woche nicht funktionstüchtig." "The upkeep for $building($building) was not paid, the building was not operational this week." - "Der Unterhalt von $building($building) konnte nur versptet gezahlt werden, das Gebude war diese Woche nicht funktionstchtig." + "Der Unterhalt von $building($building) konnte nur verspätet gezahlt werden, das Gebäude war diese Woche nicht funktionstüchtig." "The upkeep for $building($building) was paid late, the building was not operational this week." @@ -7051,7 +7072,7 @@ - "$unit($unit) verdient am Handel in $region($region) Steuern in Hhe von $int($amount) Silber." + "$unit($unit) verdient am Handel in $region($region) Steuern in Höhe von $int($amount) Silber." "$unit($unit) collected $int($amount) silver trade tax in $region($region)." @@ -7066,7 +7087,7 @@ - "Hier wtete die Pest, und $int($dead) Bauern starben." + "Hier wütete die Pest, und $int($dead) Bauern starben." "The region is visited by the plague and $int($dead) peasants died." @@ -7075,7 +7096,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Um in Gletschern Straen bauen zu knnen, mu zuerst ein Tunnel errichtet werden." + "$unit($unit) in $region($region): '$order($command)' - Um in Gletschern Straßen bauen zu können, muß zuerst ein Tunnel errichtet werden." "$unit($unit) in $region($region): '$order($command)' - You must build a tunnel before building roads through glaciers." @@ -7094,14 +7115,21 @@ - "$unit($unit) in $region($region): '$order($command)' - Deine Partei muss mindestens $int($turns) alt sein, um etwas an andere Parteien bergeben zu knnen." + "$unit($unit) in $region($region): '$order($command)' - Deine Partei muss mindestens $int($turns) alt sein, um etwas an andere Parteien übergeben zu können." "$unit($unit) in $region($region): '$order($command)' - Your faction must be at least $int($turns) weeks old to give something to another faction." - - - - "Bitte sende die Befehle nchste Runde ein, wenn du weiterspielen mchtest." + + + Deine Partei hat letzte Runde keinen Zug + abgegeben! + No orders were received for your faction! + Aucun ordre reçu pour votre faction ! + + + + + "Bitte sende die Befehle nächste Runde ein, wenn du weiterspielen möchtest." "Please send in orders for the next turn if you want to continue playing." @@ -7142,7 +7170,7 @@ - "$unit($unit) in $region($region): '$order($command)' - In dieser Regione knnen Pyramiden gebaut werden." + "$unit($unit) in $region($region): '$order($command)' - In dieser Regione können Pyramiden gebaut werden." "$unit($unit) in $region($region): '$order($command)' - Pyramids may be build in this region." @@ -7164,7 +7192,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Es ist zu gefhrlich, diesen Zauber auf das fliegende Schiff $ship($ship) zu legen." + "$unit($unit) in $region($region): '$order($command)' - Es ist zu gefährlich, diesen Zauber auf das fliegende Schiff $ship($ship) zu legen." "$unit($unit) in $region($region): '$order($command)' - It is far too dangerous to put this spell on the flying ship $ship($ship)." @@ -7176,7 +7204,7 @@ - "$unit($unit) in $region($region): '$order($command)' - In dieser Region knnen keine Pyramiden gebaut werden. Die nchste Pyramidenregion ist zwischen $int($mindist) und $int($maxdist) Regionen entfernt." + "$unit($unit) in $region($region): '$order($command)' - In dieser Region können keine Pyramiden gebaut werden. Die nächste Pyramidenregion ist zwischen $int($mindist) und $int($maxdist) Regionen entfernt." "$unit($unit) in $region($region): '$order($command)' - No pyramids may be build in this region. The closest region to build a pyramid in is between $int($mindist) and $int($maxdist) regions away." @@ -7207,7 +7235,7 @@ - "Das Wurmloch in $region($region) schliet sich." + "Das Wurmloch in $region($region) schließt sich." "The wormhole in $region($region) disappears." @@ -7230,14 +7258,14 @@ - "Der Kampf wurde ausgelst von ${factions}." + "Der Kampf wurde ausgelöst von ${factions}." "The battle was initiated by ${factions}." - "$unit($unit) konnte durch einen Heiltrank berleben." + "$unit($unit) konnte durch einen Heiltrank überleben." "$unit($unit) was saved by a healing potion." @@ -7251,7 +7279,7 @@ - "$unit($unit) berrascht den Gegner." + "$unit($unit) überrascht den Gegner." "$unit($unit) surprises the enemies." @@ -7259,7 +7287,7 @@ - "$unit($unit) versucht $spell($spell) zu zaubern, doch der Zauber schlgt fehl!" + "$unit($unit) versucht $spell($spell) zu zaubern, doch der Zauber schlägt fehl!" "$unit($unit) tries to cast $spell($spell), but the spell fails!" @@ -7312,7 +7340,7 @@ - "$unit($mage) beschwrt Trugbilder herauf." + "$unit($mage) beschwört Trugbilder herauf." "$unit($mage) summons a mirage." @@ -7320,7 +7348,7 @@ - "$unit($mage) murmelt eine dster klingende Formel. Ein pltzlicher Tumult entsteht, der sich jedoch schnell wieder legt." + "$unit($mage) murmelt eine düster klingende Formel. Ein plötzlicher Tumult entsteht, der sich jedoch schnell wieder legt." "$unit($mage) mumbles arcane words. There is a sudden hubbub, but order is restored quickly." @@ -7328,7 +7356,7 @@ - "$unit($mage) murmelt eine dster klingende Formel. Ein pltzlicher Tumult entsteht und bringt die Kampfaufstellung durcheinander." + "$unit($mage) murmelt eine düster klingende Formel. Ein plötzlicher Tumult entsteht und bringt die Kampfaufstellung durcheinander." "$unit($mage) mumbles arcane words. There is a sudden hubbub and the battle order is disturbed." @@ -7336,7 +7364,7 @@ - "$unit($mage) stimmt einen seltsamen Gesang an. Ein pltzlicher Tumult entsteht, der sich jedoch schnell wieder legt." + "$unit($mage) stimmt einen seltsamen Gesang an. Ein plötzlicher Tumult entsteht, der sich jedoch schnell wieder legt." "$unit($mage) intones a mysterious chant. There is a sudden hubbub, but order is restored quickly." @@ -7344,7 +7372,7 @@ - "$unit($mage) stimmt einen seltsamen Gesang an. Ein pltzlicher Tumult entsteht und bringt die Kampfaufstellung durcheinander." + "$unit($mage) stimmt einen seltsamen Gesang an. Ein plötzlicher Tumult entsteht und bringt die Kampfaufstellung durcheinander." "$unit($mage) begins a mysterious chant. Great confusion sweeps through the ranks of the enemy." @@ -7353,7 +7381,7 @@ - "$unit($mage) lt die Mauern von $building($building) in einem unheimlichen magischen Licht erglhen." + "$unit($mage) läßt die Mauern von $building($building) in einem unheimlichen magischen Licht erglühen." "$unit($mage) causes the walls of $building($building) to glow in an eerie magic light." @@ -7377,7 +7405,7 @@ - "$unit($mage) zaubert $spell($spell): $int($dead) $if($eq($dead,1),"Krieger wurde", "Krieger wurden") gettet." + "$unit($mage) zaubert $spell($spell): $int($dead) $if($eq($dead,1),"Krieger wurde", "Krieger wurden") getötet." "$unit($mage) casts $spell($spell): $int($dead) $if($eq($dead,1),"enemy was", "enemies were") killed." @@ -7386,7 +7414,7 @@ - "$unit($mage) lt die Erde in $region($region) erzittern." + "$unit($mage) läßt die Erde in $region($region) erzittern." "$unit($mage) makes the earth shake in $region($region)." @@ -7395,7 +7423,7 @@ - "$unit($mage) verflucht das Land in $region($region), und eine Drreperiode beginnt." + "$unit($mage) verflucht das Land in $region($region), und eine Dürreperiode beginnt." "$unit($mage) puts a curse on the lands of $region($region) and a drought sets in." @@ -7413,7 +7441,7 @@ - "$unit($mage) verliert sich in die Trume von $unit($unit) und erhlt einen Eindruck von $region($region)." + "$unit($mage) verliert sich in die Träume von $unit($unit) und erhält einen Eindruck von $region($region)." "$unit($mage) is lost in the dreams of $unit($unit) and gets a glimps into $region($region)." @@ -7423,7 +7451,7 @@ - "$unit($mage) verschafft $unit($unit) ein schnes Nachtleben in $region($region)." + "$unit($mage) verschafft $unit($unit) ein schönes Nachtleben in $region($region)." "$unit($mage) causes $unit($unit) to have a wonderful night in $region($region)." @@ -7432,7 +7460,7 @@ - "$unit($mage) sorgt fr schlechten Schlaf in $region($region)." + "$unit($mage) sorgt für schlechten Schlaf in $region($region)." "$unit($mage) disturbs everyone's dreams in $region($region)." @@ -7442,7 +7470,7 @@ - "$unit($mage) beschwrt $int($amount) $race($race,$amount)." + "$unit($mage) beschwört $int($amount) $race($race,$amount)." "$unit($mage) summons $int($amount) $race($race,$amount)." @@ -7452,7 +7480,7 @@ - "$unit($mage) erschafft in $region($region) eine verheerende Feuersbrunst. $int($amount) Bume fallen den Flammen zum Opfer." + "$unit($mage) erschafft in $region($region) eine verheerende Feuersbrunst. $int($amount) Bäume fallen den Flammen zum Opfer." "$unit($mage) creates a flaming inferno in $region($region). $int($amount) trees fall victim to the flames." @@ -7461,7 +7489,7 @@ - "Mit einem Ritual bindet $unit($mage) die magischen Krfte der Erde in die Mauern von $building($building)." + "Mit einem Ritual bindet $unit($mage) die magischen Kräfte der Erde in die Mauern von $building($building)." "A magic ritual by $unit($mage) binds magic energies to the walls of $building($building)." @@ -7479,7 +7507,7 @@ - "$unit($mage) ruft das Feuer der Sonne auf $region($region) hinab. Eis schmilzt und verwandelt sich in Morast. Reiende Strme splen die mageren Felder weg und ersufen Mensch und Tier. Was an Bauten nicht den Fluten zum Opfer fiel, verschlingt der Morast. Die sengende Hitze verndert die Region fr immer." + "$unit($mage) ruft das Feuer der Sonne auf $region($region) hinab. Eis schmilzt und verwandelt sich in Morast. Reißende Ströme spülen die mageren Felder weg und ersäufen Mensch und Tier. Was an Bauten nicht den Fluten zum Opfer fiel, verschlingt der Morast. Die sengende Hitze verändert die Region für immer." "$unit($mage) calls the torching power of the sun upon $region($region). Ice melts and turns the lands into swamps. Powerful rivers wash away the fertile soil and drown people and animals alike. What buildings have not succumbed to the floods sink into the mire. The torrid sun changes the region forever." @@ -7488,7 +7516,7 @@ - "$unit($mage) ruft das Feuer der Sonne auf $region($region) hinab. Die Felder verdorren und Pferde verdursten. Die Hungersnot kostet vielen Bauern das Leben. Vertrocknete Bume recken ihre kahlen Zweige in den blauen Himmel, von dem erbarmungslos die sengende Sonne brennt." + "$unit($mage) ruft das Feuer der Sonne auf $region($region) hinab. Die Felder verdorren und Pferde verdursten. Die Hungersnot kostet vielen Bauern das Leben. Vertrocknete Bäume recken ihre kahlen Zweige in den blauen Himmel, von dem erbarmungslos die sengende Sonne brennt." "$unit($mage) calls the torching power of the sun upon $region($region). The crops wither, horses die of thirst. A famine claims the lives of many peasants. The trees die and their bald branches cannot protect from the torrid sun that mercilessly burns the grounds." @@ -7497,7 +7525,7 @@ - "$unit($mage) ruft das Feuer der Sonne auf $region($region) hinab. Die Felder verdorren und Pferde verdursten. Die Hungersnot kostet vielen Bauern das Leben. Vertrocknete Bume recken ihre kahlen Zweige in den blauen Himmel, von dem erbarmungslos die sengende Sonne brennt. Die Drre verndert die Region fr immer." + "$unit($mage) ruft das Feuer der Sonne auf $region($region) hinab. Die Felder verdorren und Pferde verdursten. Die Hungersnot kostet vielen Bauern das Leben. Vertrocknete Bäume recken ihre kahlen Zweige in den blauen Himmel, von dem erbarmungslos die sengende Sonne brennt. Die Dürre verändert die Region für immer." "$unit($mage) calls the torching power of the sun upon $region($region). The crops wither, horses die of thirst. A famine claims the lives of many peasants. The trees die and their bald branches cannot protect from the torrid sun that mercilessly burns the grounds. The drought permanently alters the region." @@ -7511,7 +7539,7 @@ - "Die Darbietungen eines fahrenden Gauklers begeistern die Leute. Die frhliche und ausgelassene Stimmung seiner Lieder bertrgt sich auf alle Zuhrer." + "Die Darbietungen eines fahrenden Gauklers begeistern die Leute. Die fröhliche und ausgelassene Stimmung seiner Lieder überträgt sich auf alle Zuhörer." "A touring minstrel entertains the locals. The joyous and generous disposition of his songs prove infectious." @@ -7519,18 +7547,18 @@ - "Die Darbietungen von $unit($mage) begeistern die Leute. Die frhliche und ausgelassene Stimmung seiner Lieder bertrgt sich auf alle Zuhrer." + "Die Darbietungen von $unit($mage) begeistern die Leute. Die fröhliche und ausgelassene Stimmung seiner Lieder überträgt sich auf alle Zuhörer." "$unit($mage) entertains the locals. The joyous and generous disposition of his songs prove infectious." - "In der Luft liegt ein wunderschnes Lied, dessen friedfertiger Stimmung sich niemand entziehen kann. Einige Leute werfen sogar ihre Waffen weg." + "In der Luft liegt ein wunderschönes Lied, dessen friedfertiger Stimmung sich niemand entziehen kann. Einige Leute werfen sogar ihre Waffen weg." "A wondrous song fills the air and enchants the public. The song's peaceful melody makes several listeners drop their weapons." - "Die Gesangskunst von $unit($mage) begeistert die Leute. Die friedfertige Stimmung des Lieds bertrgt sich auf alle Zuhrer. Einige werfen ihre Waffen weg." + "Die Gesangskunst von $unit($mage) begeistert die Leute. Die friedfertige Stimmung des Lieds überträgt sich auf alle Zuhörer. Einige werfen ihre Waffen weg." "The marvelous singing of $unit($mage) enchants the public. The song's peaceful melody makes several listeners drop their weapons." @@ -7538,7 +7566,7 @@ - "$unit($mage) beschwrt $int($number) Dmonen aus dem Reich der Schatten." + "$unit($mage) beschwört $int($number) Dämonen aus dem Reich der Schatten." "$unit($mage) summons $int($number) demons from the realm of shadows." @@ -7558,7 +7586,7 @@ - "$unit($mage) zaubert $spell($spell). $int($amount) Krieger verloren Erinnerungen, $int($dead) wurden gettet." + "$unit($mage) zaubert $spell($spell). $int($amount) Krieger verloren Erinnerungen, $int($dead) wurden getötet." "$unit($mage) casts $spell($spell). $int($amount) warriors lose their memories, $int($dead) were killed." @@ -7568,7 +7596,7 @@ - "$unit($mage) zaubert $spell($spell). $int($amount) Krieger verloren kurzzeitig ihr Gedchtnis." + "$unit($mage) zaubert $spell($spell). $int($amount) Krieger verloren kurzzeitig ihr Gedächtnis." "$unit($mage) casts $spell($spell). $int($amount) fighters are temporarily losing some of their memories." @@ -7587,7 +7615,7 @@ - "$unit($unit) ttete $int($dead) Krieger." + "$unit($unit) tötete $int($dead) Krieger." "$unit($unit) killed $int($dead) opponents." @@ -7598,7 +7626,7 @@ - "Heer $int($index)($abbrev): $int($dead) Tote, $int($fled) Geflohene, $int($survived) berlebende." + "Heer $int($index)($abbrev): $int($dead) Tote, $int($fled) Geflohene, $int($survived) Überlebende." "Army $int($index)($abbrev): $int($dead) dead, $int($fled) fled, $int($survived) survivors." @@ -7616,7 +7644,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Dorthin fhrt kein Weg." + "$unit($unit) in $region($region): '$order($command)' - Dorthin führt kein Weg." "$unit($unit) in $region($region): '$order($command)' - There is no route leading there." @@ -7656,7 +7684,7 @@ - "$unit($self) schwcht in $region($region) einen Zauber von $unit.dative($mage) durch Antimagie ab." + "$unit($self) schwächt in $region($region) einen Zauber von $unit.dative($mage) durch Antimagie ab." "In $region($region), anti-magic from $unit($self) reduces the effect of $unit($mage)'s spell." @@ -7687,7 +7715,7 @@ - "$unit($unit) in $region($region) blst das Horn des Tanzes. In der ganzen Region breitet sich eine friedliche Feststimmmung aus." + "$unit($unit) in $region($region) bläst das Horn des Tanzes. In der ganzen Region breitet sich eine friedliche Feststimmmung aus." "$unit($unit) in $region($region) blows the Horn of Dancing. Peaceful harmony spreads over the region." @@ -7696,7 +7724,7 @@ - "$unit($unit) in $region($region) blst das Horn des Tanzes, doch niemand hier lsst sich von Stimmung anstecken." + "$unit($unit) in $region($region) bläst das Horn des Tanzes, doch niemand hier lässt sich von Stimmung anstecken." "$unit($unit) in $region($region) blows the Horn of Dancing, but nobody here gets into the mood." @@ -7717,7 +7745,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Der Magier fhlt sich durch den Trank magische gestrkt." + "$unit($unit) in $region($region): '$order($command)' - Der Magier fühlt sich durch den Trank magische gestärkt." "$unit($unit) in $region($region): '$order($command)' - The mage is magically invigorated." @@ -7746,7 +7774,7 @@ - "$unit($unit) in $region($region) erschafft eine Akademie der Knste." + "$unit($unit) in $region($region) erschafft eine Akademie der Künste." "$unit($unit) in $region($region) creates an academy of arts." @@ -7784,7 +7812,7 @@ - "$unit($unit) erscheint pltzlich." + "$unit($unit) erscheint plötzlich." "$unit($unit) appears." @@ -7826,7 +7854,7 @@ - "$unit($unit) in $region($region): '$order($command)' - $race($race,0) knnen keine Helden erwhlen." + "$unit($unit) in $region($region): '$order($command)' - $race($race,0) können keine Helden erwählen." "$unit($unit) in $region($region): '$order($command)' - $race($race,0) cannot be heroes." @@ -7847,7 +7875,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Einheit hat nur $int($have) von $int($cost) bentigtem Silber." + "$unit($unit) in $region($region): '$order($command)' - Die Einheit hat nur $int($have) von $int($cost) benötigtem Silber." "$unit($unit) in $region($region): '$order($command)' - The unit has $int($have) of $int($cost) silver required." @@ -7884,7 +7912,7 @@ - "$unit($unit) in $region($region): $int($number) $race($race,$number) $if($eq($number,1),"kehrte auf seine", "kehrten auf ihre") Felder zurck." + "$unit($unit) in $region($region): $int($number) $race($race,$number) $if($eq($number,1),"kehrte auf seine", "kehrten auf ihre") Felder zurück." "$unit($unit) in $region($region): $int($number) $race($race,$number) returned to the fields." @@ -7895,7 +7923,7 @@ - "$unit($unit) in $region($region): $int($number) $race($race,$number) $if($eq($number,1),"wurde zum Baum", "wurden zu Bumen")." + "$unit($unit) in $region($region): $int($number) $race($race,$number) $if($eq($number,1),"wurde zum Baum", "wurden zu Bäumen")." "$unit($unit) in $region($region): $int($number) $race($race,$number) turned into $if($eq($number,1),"a tree", "trees")." @@ -7928,7 +7956,7 @@ - "$unit($unit) in $region($region): $int($number) $race($race,$number) $if($eq($number,1),"verschwand", "verschwanden") ber Nacht." + "$unit($unit) in $region($region): $int($number) $race($race,$number) $if($eq($number,1),"verschwand", "verschwanden") über Nacht." "$unit($unit) in $region($region): $int($number) $race($race,$number) disappeared in the night." @@ -7939,7 +7967,7 @@ - "Der Waldbrand in $region($region) griff auch auf $region($next) ber, und $int($trees) verbrannten." + "Der Waldbrand in $region($region) griff auch auf $region($next) über, und $int($trees) verbrannten." "The fire in $region($region) spread to $region($next) and $int($trees) were burned." @@ -7991,7 +8019,7 @@ - "Die $ship($ship) ist mit gutem Wind gesegnet$if($lt($duration,3),", doch der Zauber beginnt sich bereits aufzulsen",""). ($int36($id))" + "Die $ship($ship) ist mit gutem Wind gesegnet$if($lt($duration,3),", doch der Zauber beginnt sich bereits aufzulösen",""). ($int36($id))" "The $ship($ship) is blessed with favourable winds$if($lt($duration,3),", but the spell is starting to wear thin",""). ($int36($id))" @@ -7999,7 +8027,7 @@ - "Krftige Strme haben dieses Schiff in die Luft gehoben. ($int36($id))" + "Kräftige Stürme haben dieses Schiff in die Luft gehoben. ($int36($id))" "Powerful storms have lifted this ship high into the air. ($int36($id))" @@ -8007,7 +8035,7 @@ - "Mchtige Magie verhindert den Kontakt zur Realitt. ($int36($id))" + "Mächtige Magie verhindert den Kontakt zur Realität. ($int36($id))" "Powerful magic disrupts our contact with reality. ($int36($id))" @@ -8054,7 +8082,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Die Kompassnadel springt wild hin und her und es lsst sich keine Richtung erkennen." + "$unit($unit) in $region($region): '$order($command)' - Die Kompassnadel springt wild hin und her und es lässt sich keine Richtung erkennen." "$unit($unit) in $region($region): '$order($command)' - The needle jumps wildly and there is no specific direction recognizable." @@ -8126,7 +8154,7 @@ - "Pltzlich stolpert $unit($unit) ber einige $localize($name). Nach kurzem Zgern entschlieen die $localize($name), sich Deiner Partei anzuschlieen." + "Plötzlich stolpert $unit($unit) über einige $localize($name). Nach kurzem Zögern entschließen die $localize($name), sich Deiner Partei anzuschließen." "$unit($unit) stumbles upon $localize($name). After short hesitation, $localize($name) agrees to join your faction." @@ -8134,7 +8162,7 @@ - "$unit($unit) entdeckt ein kleines Dorf. Die meisten Huser wurden durch einen ber die Ufer getretenen Flu zerstrt. Eine Gruppe der verzweifelten Menschen schliet sich deiner Partei an." + "$unit($unit) entdeckt ein kleines Dorf. Die meisten Häuser wurden durch einen über die Ufer getretenen Fluß zerstört. Eine Gruppe der verzweifelten Menschen schließt sich deiner Partei an." "$unit($unit) discovers a small village. Most of the houses have been destroyed by flooding, and a group of the distressed villagers join your faction." @@ -8165,7 +8193,7 @@ - "Dein Passwort enthlt Zeichen, die bei der Nachsendung von Reports Probleme bereiten knnen. Bitte beachte, dass Passwortenur aus Buchstaben von A bis Z und Zahlen bestehen drfen. Dein neues Passwort ist '${newpass}'." + "Dein Passwort enthält Zeichen, die bei der Nachsendung von Reports Probleme bereiten können. Bitte beachte, dass Passwortenur aus Buchstaben von A bis Z und Zahlen bestehen dürfen. Dein neues Passwort ist '${newpass}'." "Your password was changed because it contained illegal characters. Legal passwords may only contain numbers and letters from A to Z. Your new Password is '${newpass}'." @@ -8204,7 +8232,7 @@ - "In $region($region) erklingt die Stimme des Torwchters: 'Nur wer ohne materielle Gter und noch lernbegierig ist, der darf die Ebene der Herausforderung betreten. Und vergi nicht mein Trinkgeld.'. $unit($unit) erhielt keinen Einla." + "In $region($region) erklingt die Stimme des Torwächters: 'Nur wer ohne materielle Güter und noch lernbegierig ist, der darf die Ebene der Herausforderung betreten. Und vergiß nicht mein Trinkgeld.'. $unit($unit) erhielt keinen Einlaß." "$region($region) reverberates from the voice of the gate keeper: 'Only those who forgo material riches and who are willing to learn my enter the Plane of Challenge. And don't forget about my tip!'. $unit($unit) was not admitted." @@ -8213,7 +8241,7 @@ - "In $region($region) ffnet sich ein Portal. Eine Stimme ertnt, und spricht: 'Willkommen in der Ebene der Herausforderung'. $unit($unit) durchschreitet das Tor zu einer anderen Welt." + "In $region($region) öffnet sich ein Portal. Eine Stimme ertönt, und spricht: 'Willkommen in der Ebene der Herausforderung'. $unit($unit) durchschreitet das Tor zu einer anderen Welt." "A portal opens in $region($region). A voice calls: 'Welcome to the Plane of Challenge'. $unit($unit) walks through the gate to another world." @@ -8241,7 +8269,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Es ist so schn friedlich, man mchte hier niemanden angreifen." + "$unit($unit) in $region($region): '$order($command)' - Es ist so schön friedlich, man möchte hier niemanden angreifen." "$unit($unit) in $region($region): '$order($command)' - It is so quiet and peaceful, nobody wants to attack anybody right now." @@ -8253,7 +8281,7 @@ - "$unit($unit) in $region($region): '$order($command)' - $race($race,0) knnen nichts lernen." + "$unit($unit) in $region($region): '$order($command)' - $race($race,0) können nichts lernen." "$unit($unit) in $region($region): '$order($command)' - $race($race,0) cannot study." @@ -8263,7 +8291,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Migranten knnen keine kostenpflichtigen Talente lernen." + "$unit($unit) in $region($region): '$order($command)' - Migranten können keine kostenpflichtigen Talente lernen." "$unit($unit) in $region($region): '$order($command)' - Migrants cannot study this." @@ -8308,7 +8336,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Der Kapitn mu ein Segeltalent von mindestens $int($value) haben, um $ship($ship) zu befehligen." + "$unit($unit) in $region($region): '$order($command)' - Der Kapitän muß ein Segeltalent von mindestens $int($value) haben, um $ship($ship) zu befehligen." "$unit($unit) in $region($region): '$order($command)' - The captain needs a sailing skill of at least $int($value), to command $ship($ship)." @@ -8318,7 +8346,7 @@ - "$unit($unit) in $region($region): '$order($command)' - In dieser Region gibt es keine Brcken und Straen mehr zu bauen." + "$unit($unit) in $region($region): '$order($command)' - In dieser Region gibt es keine Brücken und Straßen mehr zu bauen." "$unit($unit) in $region($region): '$order($command)' - The roads and bridges in this region are complete." @@ -8339,7 +8367,7 @@ - "$unit($unit) in $region($region): '$order($command)' - Diese Einheit kmpft nicht." + "$unit($unit) in $region($region): '$order($command)' - Diese Einheit kämpft nicht." "$unit($unit) in $region($region): '$order($command)' - This unit will not fight." @@ -8369,10 +8397,20 @@ "Achtung: $faction($faction) hat seit $int($turns) Wochen keine - Zge eingeschickt und knnte dadurch in Krze aus dem Spiel + Züge eingeschickt und könnte dadurch in Kürze aus dem Spiel ausscheiden." "Warning: $faction($faction) has not been sending in orders for $int($turns) turns and may be leaving the game soon." + + + + + + + "$unit($unit) in $region($region): '$order($command)' - Helden können nicht rekrutieren." + "$unit($unit) in $region($region): '$order($command)' - Heroes cannot recruit." + + diff --git a/res/core/resources/cart.xml b/res/core/resources/cart.xml index a72b222d3..af3860c9c 100644 --- a/res/core/resources/cart.xml +++ b/res/core/resources/cart.xml @@ -1,6 +1,6 @@ - - + + diff --git a/res/core/spellbooks/cerddor.xml b/res/core/spellbooks/cerddor.xml index 50e1dbf0c..f5158f37f 100644 --- a/res/core/spellbooks/cerddor.xml +++ b/res/core/spellbooks/cerddor.xml @@ -1,4 +1,4 @@ - + diff --git a/res/core/spellbooks/draig.xml b/res/core/spellbooks/draig.xml index 592516d75..f4c66156b 100644 --- a/res/core/spellbooks/draig.xml +++ b/res/core/spellbooks/draig.xml @@ -1,4 +1,4 @@ - + diff --git a/res/core/spellbooks/gray.xml b/res/core/spellbooks/gray.xml index 6ce74e537..36e44cbd0 100644 --- a/res/core/spellbooks/gray.xml +++ b/res/core/spellbooks/gray.xml @@ -1,4 +1,4 @@ - + diff --git a/res/core/spellbooks/gwyrrd.xml b/res/core/spellbooks/gwyrrd.xml index 264bc53e4..5e07b8c7f 100644 --- a/res/core/spellbooks/gwyrrd.xml +++ b/res/core/spellbooks/gwyrrd.xml @@ -1,4 +1,4 @@ - + diff --git a/res/core/spellbooks/illaun.xml b/res/core/spellbooks/illaun.xml index 259fe68d8..cbf57aa51 100644 --- a/res/core/spellbooks/illaun.xml +++ b/res/core/spellbooks/illaun.xml @@ -1,4 +1,4 @@ - + diff --git a/res/core/spellbooks/tybied.xml b/res/core/spellbooks/tybied.xml index f6db0bfd5..a48d8e768 100644 --- a/res/core/spellbooks/tybied.xml +++ b/res/core/spellbooks/tybied.xml @@ -1,4 +1,4 @@ - + diff --git a/res/core/weapons/catapult.xml b/res/core/weapons/catapult.xml index 2ea16d9a2..08dc83457 100644 --- a/res/core/weapons/catapult.xml +++ b/res/core/weapons/catapult.xml @@ -1,6 +1,6 @@ - + diff --git a/res/e3a/messages.xml b/res/e3a/messages.xml index af781cfa5..03e5b6eb4 100644 --- a/res/e3a/messages.xml +++ b/res/e3a/messages.xml @@ -1,10 +1,10 @@ - + - "$if($isnull($mage),"Ein unentdeckter Magier",$unit($mage)) fhrt einen sonderbaren Tanz auf. Kurz darauf beginnt es zu regnen." + "$if($isnull($mage),"Ein unentdeckter Magier",$unit($mage)) führt einen sonderbaren Tanz auf. Kurz darauf beginnt es zu regnen." "$if($isnull($mage),"an unseen magician",$unit($mage)) dances a strange dance. Shortly after, rain begins to fall on the fields." diff --git a/res/e3a/races.xml b/res/e3a/races.xml index 863a5ac02..46427ba92 100644 --- a/res/e3a/races.xml +++ b/res/e3a/races.xml @@ -1,4 +1,4 @@ - + @@ -8,7 +8,7 @@ - + @@ -32,7 +32,7 @@ - + @@ -47,7 +47,7 @@ - + @@ -76,7 +76,7 @@ - + @@ -104,7 +104,7 @@ - + @@ -124,7 +124,7 @@ - + @@ -144,7 +144,7 @@ - + @@ -167,7 +167,7 @@ - + @@ -192,7 +192,7 @@ - + @@ -219,7 +219,7 @@ - + @@ -241,7 +241,7 @@ - + @@ -263,7 +263,7 @@ - + @@ -287,7 +287,7 @@ - + @@ -311,7 +311,7 @@ - + @@ -334,7 +334,7 @@ - + @@ -361,7 +361,7 @@ - + @@ -384,7 +384,7 @@ - + @@ -409,7 +409,7 @@ - + @@ -435,7 +435,7 @@ - + @@ -460,7 +460,7 @@ - + @@ -484,7 +484,7 @@ - + @@ -507,7 +507,7 @@ - + @@ -535,7 +535,7 @@ - + @@ -559,7 +559,7 @@ - + @@ -582,7 +582,7 @@ - + @@ -624,7 +624,7 @@ - + @@ -677,7 +677,7 @@ - + @@ -695,13 +695,13 @@ - + - + @@ -717,7 +717,7 @@ - + @@ -747,7 +747,7 @@ - + diff --git a/res/e3a/spellbooks/cerddor.xml b/res/e3a/spellbooks/cerddor.xml index 1f0680352..3d5f0e08e 100644 --- a/res/e3a/spellbooks/cerddor.xml +++ b/res/e3a/spellbooks/cerddor.xml @@ -1,4 +1,4 @@ - + diff --git a/res/e3a/spellbooks/common.xml b/res/e3a/spellbooks/common.xml index 67f914623..0735bc248 100644 --- a/res/e3a/spellbooks/common.xml +++ b/res/e3a/spellbooks/common.xml @@ -1,4 +1,4 @@ - + @@ -37,7 +37,7 @@ - + diff --git a/res/e3a/spellbooks/draig.xml b/res/e3a/spellbooks/draig.xml index e75363c71..34b6e7642 100644 --- a/res/e3a/spellbooks/draig.xml +++ b/res/e3a/spellbooks/draig.xml @@ -1,4 +1,4 @@ - + diff --git a/res/e3a/spellbooks/gray.xml b/res/e3a/spellbooks/gray.xml index 217bdb8b6..5967d6265 100644 --- a/res/e3a/spellbooks/gray.xml +++ b/res/e3a/spellbooks/gray.xml @@ -1,4 +1,4 @@ - + @@ -22,7 +22,7 @@ - + diff --git a/res/e3a/spellbooks/gwyrrd.xml b/res/e3a/spellbooks/gwyrrd.xml index 4de9d8da8..ac51495cf 100644 --- a/res/e3a/spellbooks/gwyrrd.xml +++ b/res/e3a/spellbooks/gwyrrd.xml @@ -1,4 +1,4 @@ - + diff --git a/res/e3a/spellbooks/illaun.xml b/res/e3a/spellbooks/illaun.xml index 020705d2f..129e15f21 100644 --- a/res/e3a/spellbooks/illaun.xml +++ b/res/e3a/spellbooks/illaun.xml @@ -1,4 +1,4 @@ - + diff --git a/res/e3a/spells.xml b/res/e3a/spells.xml index 23ce5d1a3..498777952 100644 --- a/res/e3a/spells.xml +++ b/res/e3a/spells.xml @@ -1,4 +1,4 @@ - + @@ -56,7 +56,7 @@ - + @@ -82,7 +82,7 @@ - + @@ -97,7 +97,7 @@ - + @@ -114,11 +114,11 @@ - + - + @@ -149,7 +149,7 @@ - + @@ -162,7 +162,7 @@ - + @@ -184,7 +184,7 @@ - + @@ -235,7 +235,7 @@ - + @@ -288,7 +288,7 @@ - + @@ -330,7 +330,7 @@ - + @@ -342,12 +342,12 @@ - + - + @@ -381,7 +381,7 @@ - + @@ -404,15 +404,15 @@ - + - + - + @@ -420,7 +420,7 @@ - + @@ -429,9 +429,9 @@ - + - + @@ -448,7 +448,7 @@ - + @@ -458,9 +458,9 @@ - + - + @@ -619,7 +619,7 @@ - + diff --git a/res/e3a/strings.xml b/res/e3a/strings.xml index 9c1ca68f1..d0647a6d1 100644 --- a/res/e3a/strings.xml +++ b/res/e3a/strings.xml @@ -1,7 +1,7 @@ - + diff --git a/res/eressea/items.xml b/res/eressea/items.xml index f3f59490f..076cc023c 100644 --- a/res/eressea/items.xml +++ b/res/eressea/items.xml @@ -1,4 +1,4 @@ - + diff --git a/res/eressea/races.xml b/res/eressea/races.xml index 02d530da3..26a63752f 100644 --- a/res/eressea/races.xml +++ b/res/eressea/races.xml @@ -1,16 +1,16 @@ - + + fly="no" walk="no" canteach="no" getitem="yes"> - + @@ -26,7 +26,7 @@ - + @@ -60,7 +60,7 @@ - + @@ -89,7 +89,7 @@ - + @@ -117,7 +117,7 @@ - + @@ -147,7 +147,7 @@ - + @@ -177,7 +177,7 @@ - + @@ -208,7 +208,7 @@ - + @@ -243,7 +243,7 @@ - + @@ -274,7 +274,7 @@ - + @@ -307,7 +307,7 @@ - + @@ -338,7 +338,7 @@ - + @@ -369,7 +369,7 @@ - + @@ -400,7 +400,7 @@ - + @@ -430,7 +430,7 @@ - + @@ -462,7 +462,7 @@ - + @@ -494,7 +494,7 @@ - + @@ -524,7 +524,7 @@ - + @@ -557,7 +557,7 @@ - + @@ -605,7 +605,7 @@ - + @@ -674,7 +674,7 @@ - + @@ -692,13 +692,13 @@ - + - + @@ -713,14 +713,14 @@ - + - + @@ -745,7 +745,7 @@ - + @@ -785,7 +785,7 @@ - + @@ -804,7 +804,7 @@ - + @@ -830,7 +830,7 @@ - + @@ -863,7 +863,7 @@ - + @@ -892,7 +892,7 @@ - + @@ -924,7 +924,7 @@ - + @@ -955,7 +955,7 @@ - + @@ -981,7 +981,7 @@ - + @@ -1014,7 +1014,7 @@ - + @@ -1137,7 +1137,7 @@ - + @@ -1181,7 +1181,7 @@ - + @@ -1212,7 +1212,7 @@ - - + @@ -1269,7 +1269,7 @@ - + @@ -1301,7 +1301,7 @@ - + diff --git a/res/eressea/spellbooks/cerddor.xml b/res/eressea/spellbooks/cerddor.xml index 0609b0141..3a690b116 100644 --- a/res/eressea/spellbooks/cerddor.xml +++ b/res/eressea/spellbooks/cerddor.xml @@ -1,4 +1,4 @@ - + @@ -27,7 +27,7 @@ - + diff --git a/res/eressea/spellbooks/gray.xml b/res/eressea/spellbooks/gray.xml index 4356cde5e..21e1609a0 100644 --- a/res/eressea/spellbooks/gray.xml +++ b/res/eressea/spellbooks/gray.xml @@ -1,4 +1,4 @@ - + @@ -26,7 +26,7 @@ - + @@ -142,7 +142,7 @@ - + diff --git a/res/eressea/spellbooks/gwyrrd.xml b/res/eressea/spellbooks/gwyrrd.xml index 68d0c4ff0..42863df34 100644 --- a/res/eressea/spellbooks/gwyrrd.xml +++ b/res/eressea/spellbooks/gwyrrd.xml @@ -1,4 +1,4 @@ - + diff --git a/res/eressea/spellbooks/illaun.xml b/res/eressea/spellbooks/illaun.xml index 81825e424..37f3e73b2 100644 --- a/res/eressea/spellbooks/illaun.xml +++ b/res/eressea/spellbooks/illaun.xml @@ -1,4 +1,4 @@ - + @@ -8,7 +8,7 @@ - + diff --git a/res/eressea/spellbooks/tybied.xml b/res/eressea/spellbooks/tybied.xml index 791180c19..9c64f22ca 100644 --- a/res/eressea/spellbooks/tybied.xml +++ b/res/eressea/spellbooks/tybied.xml @@ -1,4 +1,4 @@ - + diff --git a/res/eressea/spellinfo.xml b/res/eressea/spellinfo.xml index ce2e82635..2dfef6b12 100644 --- a/res/eressea/spellinfo.xml +++ b/res/eressea/spellinfo.xml @@ -1,30 +1,30 @@ - + Dieses uralte Tanzritual ruft die - Krfte des Lebens und der Fruchtbarkeit. Die Ertrge der - Bauern werden fr einige Wochen deutlich besser + Kräfte des Lebens und der Fruchtbarkeit. Die Erträge der + Bauern werden für einige Wochen deutlich besser ausfallen. This ancient rite calls upon the forces of life and fertility. For the next few weeks, the peasant's harvest will be extraordinary good. - Dieses Ernteritual verbessert die Ertrge der - arbeitenden Bauern in der Region um ein Silberstck. Je mehr Kraft der - Druide investiert, desto lnger wirkt der Zauber. + Dieses Ernteritual verbessert die Erträge der + arbeitenden Bauern in der Region um ein Silberstück. Je mehr Kraft der + Druide investiert, desto länger wirkt der Zauber. This ritual increases the output of the local farms. Peasants in the region produce an extra silverpiece. The stronger the druid's spell is, the longer the effect will last. Wenn einem der Alchemist nicht weiterhelfen kann, geht man zu dem - gelehrten Tybiedmagier. Seine Trnke und Tinkturen helfen gegen + gelehrten Tybiedmagier. Seine Tränke und Tinkturen helfen gegen alles, was man sonst nicht bekommen kann. Ob nun die kryptische Formel unter dem Holzschuh des untreuen Ehemannes wirklich geholfen - hat - nun, der des Lesens nicht mchtige Bauer wird es nie wissen. - Dem Magier hilft es auf jeden Fall... beim Fllen seines + hat - nun, der des Lesens nicht mächtige Bauer wird es nie wissen. + Dem Magier hilft es auf jeden Fall... beim Füllen seines Geldbeutels. 50 Silber pro Stufe lassen sich so in einer Woche verdienen. If the local alchemist could not help you, you should visit a @@ -38,10 +38,10 @@ Cerddormagier sind _die_ Gaukler unter den Magiern, sie lieben es das Volk zu unterhalten und - im Mittelpunkt zu stehen. Schon Anfnger lernen die - kleinen Kunststcke und magischen Tricks, mit denen man - das Volk locken und verfhren kann, den Geldbeutel ganz - weit zu ffnen, und am Ende der Woche wird der Gaukler + im Mittelpunkt zu stehen. Schon Anfänger lernen die + kleinen Kunststücke und magischen Tricks, mit denen man + das Volk locken und verführen kann, den Geldbeutel ganz + weit zu öffnen, und am Ende der Woche wird der Gaukler 50 Silber pro Stufe verdient haben. The mages of Cerddor truly are the bards of the wizards; they love to use their sorcery to @@ -53,11 +53,11 @@ per level. - Die Fhigkeiten der Gwyrrd-Magier in + Die Fähigkeiten der Gwyrrd-Magier in der Viehzucht und Heilung sind bei den Bauern sehr - begehrt. Gerade auf Mrkten sind ihre Dienste hufig sehr + begehrt. Gerade auf Märkten sind ihre Dienste häufig sehr gefragt. Manch einer mag auch sein Talent dazu nutzen, - ein Tier fr einen besseren Preis zu verkaufen. Pro + ein Tier für einen besseren Preis zu verkaufen. Pro Stufe kann der Magier so 50 Silber verdienen. The abilities of the mages of Gwyrrd concerning the breeding and healing of cattle are highly @@ -69,13 +69,13 @@ In den dunkleren Gassen gibt es sie, - die Flche und Verhexungen auf Bestellung. Aber - auch Gegenzauber hat der Jnger des Draigs - natrlich im Angebot. Ob nun der Sohn des + die Flüche und Verhexungen auf Bestellung. Aber + auch Gegenzauber hat der Jünger des Draigs + natürlich im Angebot. Ob nun der Sohn des Nachbarn in einen Liebesbann gezogen werden soll oder die Nebenbuhlerin Pickel und Warzen bekommen soll, niemand gibt gerne zu, zu solchen - Mitteln gegriffen zu haben. Fr diese + Mitteln gegriffen zu haben. Für diese Dienstleistung streicht der Magier 50 Silber pro Stufe ein. In the dark alleys you can find those @@ -88,18 +88,18 @@ per level. - Personne n'interprte aussi bien les - rves que les mages d'Illaun. Ils sont galement - verss dans l'utilisation des objets utiliss - pour prdire le futur comme les boules de + Personne n'interprète aussi bien les + rêves que les mages d'Illaun. Ils sont également + versés dans l'utilisation des objets utilisés + pour prédire le futur comme les boules de cristal, les cartes de tarot ou les lignes de la - main. Un mentaliste peut gagner 50 cus par + main. Un mentaliste peut gagner 50 écus par niveau et par semaine en proposant ses services aux paysans. - Niemand kann so gut die Trume deuten + Niemand kann so gut die Träume deuten wie ein Magier des Illaun. Auch die Kunst der Wahrsagerei, des Kartenlegens und des Handlesens - sind ihm gelufig. Dafr zahlen ihm die Bauern + sind ihm geläufig. Dafür zahlen ihm die Bauern 50 Silber pro Stufe. No one can read dreams as well as the mages of Illaun. Furthermore, they are also diff --git a/res/eressea/spells.xml b/res/eressea/spells.xml index 23da434b5..345541298 100644 --- a/res/eressea/spells.xml +++ b/res/eressea/spells.xml @@ -188,11 +188,13 @@ + @@ -400,7 +402,7 @@ - + diff --git a/res/eressea/strings.xml b/res/eressea/strings.xml index 387ca981e..551551ae7 100644 --- a/res/eressea/strings.xml +++ b/res/eressea/strings.xml @@ -1,43 +1,32 @@ - + - - Dieser Zauber wird die gesamte Ausrstung der - Zieleinheit fr - einige Zeit vor den Blicken anderer verschleiern. Der - Zauber - schtzt nicht vor Dieben und Spionen. - This spell will hide the whole equipment of a target - unit from the - looks of others. It will not protect against thieves or - spies. - Aufzeichung des Vortrags von Selen Ard'Ragorn in Bar'Glingal: - 'Es heiss, dieser Spruch wre wohl in den Spelunken der Westgassen + 'Es heiss, dieser Spruch wäre wohl in den Spelunken der Westgassen entstanden, doch es kann genausogut in jedem andern verrufenen Viertel gewesen sein. Seine wichtigste Zutat ist etwa ein Fass schlechtesten Weines, je billiger und ungesunder, desto wirkungsvoller wird die Essenz. Die Kunst, diesen Wein in pure Essenz zu destillieren, die weitaus anspruchsvoller als das einfache Rezeptmischen eines Alchemisten ist, und diese dergestalt zu binden - und konservieren, das sie sich nicht gleich wieder verflchtigt, wie - es ihre Natur wre, ja, dies ist etwas, das nur ein Meister des + und konservieren, das sie sich nicht gleich wieder verflüchtigt, wie + es ihre Natur wäre, ja, dies ist etwas, das nur ein Meister des Cerddor vollbringen kann. Nun besitzt Ihr eine kleine Phiola mit - einer rubinrotschimmernden - nun, nicht flssig, doch auch nicht + einer rubinrotschimmernden - nun, nicht flüssig, doch auch nicht ganz Dunst - nennen wir es einfach nur Elixier. Doch nicht dies ist die wahre Herausforderung, sodann muss, da sich ihre Wirkung leicht - verflchtigt, diese innerhalb weniger Tage unbemerkt in das Getrnk - des Opfers getrufelt werden. Ihr Meister der Bethrung und - Verfhrung, hier nun knnt Ihr Eure ganze Kunst unter Beweis + verflüchtigt, diese innerhalb weniger Tage unbemerkt in das Getränk + des Opfers geträufelt werden. Ihr Meister der Betöhrung und + Verführung, hier nun könnt Ihr Eure ganze Kunst unter Beweis stellen. Doch gebt Acht, nicht unbedacht selbst von dem Elixier zu kosten, denn wer einmal gekostet hat, der kann vom Weine nicht mehr - lassen, und er suft sicherlich eine volle Woche lang. Jedoch nicht - die Verfhrung zum Trunke ist die wahre Gefahr, die dem Elixier + lassen, und er säuft sicherlich eine volle Woche lang. Jedoch nicht + die Verführung zum Trunke ist die wahre Gefahr, die dem Elixier innewohnt, sondern das der Trunkenheit so sicher ein gar - frchterliches Leid des Kopfes folgen wird, wie der Tag auf die - Nacht folgt. Und er wird gar sicherlich von seiner besten Fhigkeit + fürchterliches Leid des Kopfes folgen wird, wie der Tag auf die + Nacht folgt. Und er wird gar sicherlich von seiner besten Fähigkeit einige Tage bis hin zu den Studien zweier Wochen vergessen haben. Noch ein Wort der Warnung: Dieses ist sehr aufwendig, und so Ihr noch weitere Zauber in der selben Woche wirken wollt, so werden sie Euch @@ -47,11 +36,11 @@ Mit diesem Spruch kann der Traumweber versuchen, die Verzauberungen einer einzelnen - Einheit zu erkennen. Von allen Sprchen, die - seine eigenen Fhigkeiten nicht berschreiten, + Einheit zu erkennen. Von allen Sprüchen, die + seine eigenen Fähigkeiten nicht überschreiten, wird er einen Eindruck ihres Wirkens erhalten - knnen. Bei strkeren Sprchen bentigt er ein - wenig Glck fr eine gelungene Analyse. + können. Bei stärkeren Sprüchen benötigt er ein + wenig Glück für eine gelungene Analyse. With this spell the mentalist can attempt to detect enchantments on a target unit. He will get an idea of the effect of all spells @@ -76,35 +65,35 @@ snowman - Schneemnner + Schneemänner snowmen - Keine Informationen ber diesen Schiffstyp verfgbar. + Keine Informationen über diesen Schiffstyp verfügbar. No Information available for this type of ship. - Der Sumpfgasballon besteht aus einem groen + Der Sumpfgasballon besteht aus einem großen Weidenkorb, welcher Platz - fr maximal 5 Personen oder 500 Gewichtseinheiten bietet, und einer - groen, mit Sumpfgas gefllten Wyrmblase. Bei guten Winden kann sich - der Ballon zwei Regionen pro Woche fortbewegen. Das Fhren eines - Ballons ist nicht einfach, und der Kapitn muss mindestens ein + für maximal 5 Personen oder 500 Gewichtseinheiten bietet, und einer + großen, mit Sumpfgas gefüllten Wyrmblase. Bei guten Winden kann sich + der Ballon zwei Regionen pro Woche fortbewegen. Das Führen eines + Ballons ist nicht einfach, und der Kapitän muss mindestens ein Segeltalent von 6 besitzen. Diese neue Entwicklung auf Eressea wird - ausschlielich fr den Xontormia-Expre hergestellt und die Bauplne + ausschließlich für den Xontormia-Expreß hergestellt und die Baupläne sind streng geheim. So ist es auch bisher noch niemandem gelungen, ein Exemplar nachzubauen. - Benutzt der Kapitn des Schiffes diesen Talisman, so wird allen an Bord befindlichen Mallornsamen ihre magisch Energie entzogen, und das Schiff kann mit dieser Energie bis zu zwei Wochen lang fliegen. + Benutzt der Kapitän des Schiffes diesen Talisman, so wird allen an Bord befindlichen Mallornsamen ihre magisch Energie entzogen, und das Schiff kann mit dieser Energie bis zu zwei Wochen lang fliegen. - Eine Geburtstagstorte mit 10 Kerzen. Herzlichen Glckwunsch, Eressea! + Eine Geburtstagstorte mit 10 Kerzen. Herzlichen Glückwunsch, Eressea! A birthday cake with 10 candles. Happy Birthday, Eressea! @@ -112,98 +101,98 @@ No Information available. - Dieses Fluggert aus der Schmiede der Zwerge von Celeband galt wie die + Dieses Fluggerät aus der Schmiede der Zwerge von Celeband galt wie die 'Ebene der Herausforderung' seit Urzeiten als verschollen, ja man - zweifelte seine Existenz an. Die Sage berliefert, das derjenige, der + zweifelte seine Existenz an. Die Sage überliefert, das derjenige, der sie auf der Spitze des Turmes seiner Gesinnung benutzt, als einziger die 'Ebene der Herausforderungen' verlassen kann. - Glckwunsch, mein Kind. Du bist im Besitz des mchtigsten + Glückwunsch, mein Kind. Du bist im Besitz des mächtigsten Artefaktes Eresseas. Ein Fluch, sagt man, liege auf ihm, denn niemand hat es bisher lange sein Eigen genannt... - Kleines trockenes Dauergebck, m od. s; - u. -es, - u. -e + Kleines trockenes Dauergebäck, m od. s; - u. -es, - u. -e So wisse denn, dass das Auge des Drachen den Weg zur Herausforderung - aufzeigt. Doch die berlieferung sagt, das nur der Unschuldige und - Ungewappnete es benutzen kann. Sie sagt auch, da er einen Beutel mit - einem Betrag von bis zu zweitausend Silber mit sich fhren soll, - jedoch nicht mehr als einem Fnftel der Strke seines Volkes - entsprechend - dem Torwchter zum Geschenke als Beweis seiner + aufzeigt. Doch die Überlieferung sagt, das nur der Unschuldige und + Ungewappnete es benutzen kann. Sie sagt auch, daß er einen Beutel mit + einem Betrag von bis zu zweitausend Silber mit sich führen soll, + jedoch nicht mehr als einem Fünftel der Stärke seines Volkes + entsprechend - dem Torwächter zum Geschenke als Beweis seiner asketischen Gesinnung. Die 5 scheidet ganz aus. - (Prunus dulcis) [...] Die Nsse existieren in zwei Varianten, s und - bitter. Se Mandeln sind der bekannte ebare Typ, der in Form von - Nssen gegessen, beim Kochen verwandt oder zu Mandell und Mandelmehl + (Prunus dulcis) [...] Die Nüsse existieren in zwei Varianten, süß und + bitter. Süße Mandeln sind der bekannte eßbare Typ, der in Form von + Nüssen gegessen, beim Kochen verwandt oder zu Mandelöl und Mandelmehl verarbeitet wird. A tasty fruit. - Frucht aus der Gattung Malus (ca. 25 Arten), gehrt + Frucht aus der Gattung Malus (ca. 25 Arten), gehört zur Familie der - Rosengewchse. Die am hufigsten kultivierte Baumfrucht. Der Apfel - gehrt zu den fleischigen Frchten, in dem der gereifte Fruchtknoten + Rosengewächse. Die am häufigsten kultivierte Baumfrucht. Der Apfel + gehört zu den fleischigen Früchten, in dem der gereifte Fruchtknoten und - das umgebende Gewebe fleischig und ebar werden. Die Apfelblte der - meisten Varianten erfordert Kreuzbestubung zur Befruchtung. Form und - Gre des Apfels bei der Ernte variieren abhngig von kulturellen und - umweltbedingten Einflssen in Gre, Form, Farbe und Geschmack, sind - jedoch nichtsdestotrotz blicherweise rund, zwischen 50 und 100mm im - Durchmesser und weisen rt- oder gelbliche Farbtne auf. + das umgebende Gewebe fleischig und eßbar werden. Die Apfelblüte der + meisten Varianten erfordert Kreuzbestäubung zur Befruchtung. Form und + Größe des Apfels bei der Ernte variieren abhängig von kulturellen und + umweltbedingten Einflüssen in Größe, Form, Farbe und Geschmack, sind + jedoch nichtsdestotrotz üblicherweise rund, zwischen 50 und 100mm im + Durchmesser und weisen röt- oder gelbliche Farbtöne auf. - Nu, im umgangssprachlichen Sinne alle trockenen, + Nuß, im umgangssprachlichen Sinne alle trockenen, hartschaligen - Frchte oder Samen, die eine Schale besitzen, die sich leicht - vom inneren, ebaren Kern entfernen lt. In der botanischen - Terminologie beschrnkt sich die Bezeichnung Nu auf eine + Früchte oder Samen, die eine Schale besitzen, die sich leicht + vom inneren, eßbaren Kern entfernen läßt. In der botanischen + Terminologie beschränkt sich die Bezeichnung Nuß auf eine einsamige Frucht, die aus einem Fruchtknoten (Ovarium) - entstanden ist, dessen uere Wnde sich verholzt haben und der - sich nicht ffnet, um seinen Samen zu entlassen. Solche echten - Nsse knnen ebar, aber auch ungeniebar sein. Bekannte - Beispiele sind Eicheln, Bucheckern, Kastanien und Haselnsse. - Beispiele fr Frchte oder Samen, die vom Volksmund flschlich - als Nsse bezeichnet werden, sind Mandeln und Walnsse: Im - botanischen Sinne sind dies Steinfrchte, denen die fleischige - uere Schale entfernt wurde. Andere Beispiele fr unechte - Nsse sind Erdnsse - in Hlsen eingeschlossene Samen - sowie - Rokastanien und Paransse, bei denen es sich um von Kapseln - umhllte Samen handelt. + entstanden ist, dessen äußere Wände sich verholzt haben und der + sich nicht öffnet, um seinen Samen zu entlassen. Solche echten + Nüsse können eßbar, aber auch ungenießbar sein. Bekannte + Beispiele sind Eicheln, Bucheckern, Kastanien und Haselnüsse. + Beispiele für Früchte oder Samen, die vom Volksmund fälschlich + als Nüsse bezeichnet werden, sind Mandeln und Walnüsse: Im + botanischen Sinne sind dies Steinfrüchte, denen die fleischige + äußere Schale entfernt wurde. Andere Beispiele für unechte + Nüsse sind Erdnüsse - in Hülsen eingeschlossene Samen - sowie + Roßkastanien und Paranüsse, bei denen es sich um von Kapseln + umhüllte Samen handelt. - Zwerge schufen diesen wunderschnen Ring aus Weissgold und Platin. Die - Oberflche ist so glatt, dass man nur bei genauem Hinsehen entdeckt, + Zwerge schufen diesen wunderschönen Ring aus Weissgold und Platin. Die + Oberfläche ist so glatt, dass man nur bei genauem Hinsehen entdeckt, dass hier eigentlich zwei Metalle ineinander verarbeitet worden sind. In der Innenseite des Rings ist eine Gravur zu lesen: "Wildente, 3. Woche Eiswind Jahr 8". - Dieses Brautkleid ist mit Abstand das schnste, was je jemand + Dieses Brautkleid ist mit Abstand das schönste, was je jemand irgendwie irgendwo gesehen hat. Auch wenn nur Wildente und Jadee das - finden mssten, wird jeder Bewohner Eresseas dies neidlos besttigen. - Das sehr stilvolle Kleid lsst die zarten Schultern seiner Trgerin - frei und liegt am Oberkrper eng an. Dies betont atemberaubend die - zarten Kurven der Braut. Der Rock fllt leicht ausgestellt den ganzen + finden müssten, wird jeder Bewohner Eresseas dies neidlos bestätigen. + Das sehr stilvolle Kleid lässt die zarten Schultern seiner Trägerin + frei und liegt am Oberkörper eng an. Dies betont atemberaubend die + zarten Kurven der Braut. Der Rock fällt leicht ausgestellt den ganzen langen Weg an den Beinen herunter Richtung Boden, wo er sich in einer sehr stilvollen Schleppe ergiesst. Dieser Ring ist ein wahres Meisterwerk. Obwohl er sehr gross ist - (weil auch sein Trger sehr gross ist), wirkt er filigran. Weissgold + (weil auch sein Träger sehr gross ist), wirkt er filigran. Weissgold und Platin verschmelzen in diesem Ring zu einer Einheit, die die - Schnheit der einzelnen Elemente nur noch unterstreich. In der + Schönheit der einzelnen Elemente nur noch unterstreich. In der Innenseite des Rings ist eine Gravur zu lesen: 'Jadee, 3. Woche Eiswind Jahr 8'. Hach! Sieht der Mann beeindruckend aus in diesem Frack! Und so - ordentlich! Und so ernst! Und so beeindruckend! Es fllt ein - wenig schwer, sich auf den Brutigam zu konzentrieren, weil das - Brautkleid noch daneben strahlt, aber der Anzug des Brutigams ist + ordentlich! Und so ernst! Und so beeindruckend! Es fällt ein + wenig schwer, sich auf den Bräutigam zu konzentrieren, weil das + Brautkleid noch daneben strahlt, aber der Anzug des Bräutigams ist auf jeden Fall so, wie er sein soll und sieht toll aus und sehr geschmackvoll. @@ -211,7 +200,7 @@ Orange nose, black hat, frosty character. A snowman. He'll make a fine guard if you use him in a cold place. (USE 1 snowman) - Rbennase, schwarzer Hut, kaltes Herz. Ein Schneemann. Er gibt + Rübennase, schwarzer Hut, kaltes Herz. Ein Schneemann. Er gibt einen prima Wachmann ab, wenn er in einem Gletscher belebt wird (BENUTZE 1 Schneemann). @@ -219,12 +208,12 @@ These items stay frozen all year round. There seem to be bits of ice in them - in the right hands, these might put an eye out! Ein Schneeball. Es scheinen kleine Eissplitter darin zu sein. In - den richtigen Hnden knnen sie sicher weh tun. + den richtigen Händen können sie sicher weh tun. This badge pronounces its wearer an official visitor to the embassies of Muschelplateau. - Dieses Abzeichen identifiziert die Partei seines Trgers offiziell + Dieses Abzeichen identifiziert die Partei seines Trägers offiziell als einen Besucher der Botschafterregion 'Muschelplateau'. @@ -265,8 +254,8 @@ - Die ersten beiden Zge mut du abgeben, sonst wird deine - Partei sofort wieder gelscht, um Karteileichen zu vermeiden. + Die ersten beiden Züge mußt du abgeben, sonst wird deine + Partei sofort wieder gelöscht, um Karteileichen zu vermeiden. If you fail to send in orders for one of the first two turns, your faction will be erased from the game to reduce the number of inactive players in Eressea. @@ -291,7 +280,7 @@ Seeschlangenkopf - Seeschlangenkpfe + Seeschlangenköpfe @@ -341,7 +330,7 @@ - Frcke + Fräcke tuxedos @@ -362,15 +351,15 @@ horn of dancing - Hrner des Tanzes + Hörner des Tanzes horns of dancing - Miniatur einer Akademie der Knste + Miniatur einer Akademie der Künste academy of arts in a box - Miniaturen einer Akademie der Knste + Miniaturen einer Akademie der Künste academies of arts in a box @@ -394,7 +383,7 @@ aura potion - Auratrnke + Auratränke aura potions @@ -402,21 +391,21 @@ bagpipe of fear - Dudelscke der Furcht + Dudelsäcke der Furcht bagpipes of fear - Auge des Dmon + Auge des Dämon eye of the demon - oeil du dmon + oeil du démon - Augen des Dmon + Augen des Dämon eyes of the demon - oeil du dmon + oeil du démon Schwinge des Greifen @@ -448,16 +437,16 @@ adamantium axe - Adamantiumxte + Adamantiumäxte adamantium axes - Adamantiumrstung + Adamantiumrüstung adamantium plate - Adamantiumrstungen + Adamantiumrüstungen adamantium plates diff --git a/res/eressea/terrains.xml b/res/eressea/terrains.xml index 8b2ce7b1c..e506c5dd4 100644 --- a/res/eressea/terrains.xml +++ b/res/eressea/terrains.xml @@ -1,4 +1,4 @@ - + diff --git a/res/items.xml b/res/items.xml index e8fa7246a..108e6d398 100644 --- a/res/items.xml +++ b/res/items.xml @@ -1,3 +1,3 @@ - + diff --git a/res/names-dragons.xml b/res/names-dragons.xml index 1b0abf4c1..7272ba052 100644 --- a/res/names-dragons.xml +++ b/res/names-dragons.xml @@ -1,4 +1,4 @@ - + @@ -8,16 +8,16 @@ der Allwissende - der Mchtige + der Mächtige - die Ehrwrdige + die Ehrwürdige die Listige - der Grne + der Grüne die Strafende @@ -44,7 +44,7 @@ die Alte - die Mchtige + die Mächtige die Goldene @@ -62,7 +62,7 @@ die Verzehrende - die Grne + die Grüne die Rote @@ -71,16 +71,16 @@ der Furchtlose - der Allmchtige + der Allmächtige der Weitblickende - der Weie + der Weiße - die Glnzende + die Glänzende der Wissende @@ -89,7 +89,7 @@ die Unbarmherzige - die Schne + die Schöne diff --git a/res/names-ghouls.xml b/res/names-ghouls.xml index 474156c55..4d8c938d9 100644 --- a/res/names-ghouls.xml +++ b/res/names-ghouls.xml @@ -1,11 +1,11 @@ - + Faulende - Angsteinflende + Angsteinflößende Leise @@ -29,7 +29,7 @@ Dunkle - Frchterliche + Fürchterliche Grauenhafte @@ -47,7 +47,7 @@ Schreckliche - Dstere + Düstere Schaurige @@ -82,7 +82,7 @@ der Finsternis - des Bsen + des Bösen der Erschlagenen diff --git a/res/names-skeletons.xml b/res/names-skeletons.xml index 47554d6ae..8e282ae74 100644 --- a/res/names-skeletons.xml +++ b/res/names-skeletons.xml @@ -1,11 +1,11 @@ - + Klapperige - Sthnende + Stöhnende Schwarzknochige @@ -14,7 +14,7 @@ Schwarzgewandete - Angsteinflende + Angsteinflößende Heulende @@ -32,7 +32,7 @@ Dunkle - Frchterliche + Fürchterliche Grauenhafte @@ -50,7 +50,7 @@ Schreckliche - Dstere + Düstere Schaurige @@ -69,10 +69,10 @@ Krieger - Kmpfer + Kämpfer - Rcher + Rächer @@ -85,7 +85,7 @@ der Finsternis - des Bsen + des Bösen der Erschlagenen diff --git a/res/names-undead.xml b/res/names-undead.xml index 4623b9710..058bdef26 100644 --- a/res/names-undead.xml +++ b/res/names-undead.xml @@ -1,10 +1,10 @@ - + Grausige - Sthnende + Stöhnende Schlurfende @@ -16,7 +16,7 @@ Faulende - Angsteinflende + Angsteinflößende Heulende @@ -34,7 +34,7 @@ Dunkle - Frchterliche + Fürchterliche Grauenhafte @@ -58,7 +58,7 @@ Ekelhafte - Dstere + Düstere Schaurige @@ -120,7 +120,7 @@ der Finsternis - des Bsen + des Bösen der Erschlagenen diff --git a/res/names-zombies.xml b/res/names-zombies.xml index d494b9380..cbad1951f 100644 --- a/res/names-zombies.xml +++ b/res/names-zombies.xml @@ -1,4 +1,4 @@ - + Faulende @@ -10,7 +10,7 @@ Gefolterte - Angsteinflende + Angsteinflößende Leise Schlurfende @@ -25,7 +25,7 @@ Dunkle - Frchterliche + Fürchterliche Grauenhafte @@ -43,7 +43,7 @@ Schreckliche - Dstere + Düstere Schaurige @@ -75,7 +75,7 @@ der Finsternis - des Bsen + des Bösen der Erschlagenen diff --git a/res/races.xml b/res/races.xml index 09ce2212e..fcfc1742b 100644 --- a/res/races.xml +++ b/res/races.xml @@ -1,4 +1,4 @@ - + diff --git a/res/races/aquarian.xml b/res/races/aquarian.xml index 0bd11c8c3..776f17e93 100644 --- a/res/races/aquarian.xml +++ b/res/races/aquarian.xml @@ -1,5 +1,5 @@ - - + + diff --git a/res/races/cat.xml b/res/races/cat.xml index d71d41b92..818b24b36 100644 --- a/res/races/cat.xml +++ b/res/races/cat.xml @@ -1,5 +1,5 @@ - + diff --git a/res/races/demon.xml b/res/races/demon.xml index ba187acfd..9f97d4d8f 100644 --- a/res/races/demon.xml +++ b/res/races/demon.xml @@ -1,5 +1,5 @@ - - + + diff --git a/res/races/dragon.xml b/res/races/dragon.xml index ecb7e04da..7a6dee3a7 100644 --- a/res/races/dragon.xml +++ b/res/races/dragon.xml @@ -1,5 +1,5 @@ +"6" damage="2d30" unarmedattack="0" unarmeddefense="0" attackmodifier="7" defensemodifier="7" scarepeasants="yes" fly="yes" walk="yes" teach="no" getitem="yes" resistbash="yes"> diff --git a/res/races/dwarf.xml b/res/races/dwarf.xml index a718581a7..20fb874c0 100644 --- a/res/races/dwarf.xml +++ b/res/races/dwarf.xml @@ -1,5 +1,5 @@ - - + + diff --git a/res/races/elf.xml b/res/races/elf.xml index 678422652..dfbd2f2ec 100644 --- a/res/races/elf.xml +++ b/res/races/elf.xml @@ -1,5 +1,5 @@ - - + + diff --git a/res/races/goblin-2.xml b/res/races/goblin-2.xml index 7e23e28cf..e91781aa6 100644 --- a/res/races/goblin-2.xml +++ b/res/races/goblin-2.xml @@ -1,5 +1,5 @@ - - + + diff --git a/res/races/goblin-3.xml b/res/races/goblin-3.xml index 845b69c20..a59ee6f77 100644 --- a/res/races/goblin-3.xml +++ b/res/races/goblin-3.xml @@ -1,5 +1,5 @@ - - + + diff --git a/res/races/goblin.xml b/res/races/goblin.xml index da2ee2907..af097396c 100644 --- a/res/races/goblin.xml +++ b/res/races/goblin.xml @@ -1,5 +1,5 @@ - - + + diff --git a/res/races/halfling.xml b/res/races/halfling.xml index 0e61aa55d..3875ca414 100644 --- a/res/races/halfling.xml +++ b/res/races/halfling.xml @@ -1,5 +1,5 @@ - - + + diff --git a/res/races/human.xml b/res/races/human.xml index 0d689b4ac..2e4b94af2 100644 --- a/res/races/human.xml +++ b/res/races/human.xml @@ -1,5 +1,5 @@ - - + + diff --git a/res/races/insect.xml b/res/races/insect.xml index d727e1ee4..cecbf0193 100644 --- a/res/races/insect.xml +++ b/res/races/insect.xml @@ -1,5 +1,5 @@ - - + + diff --git a/res/races/orc.xml b/res/races/orc.xml index 2caaaf8e5..d9d26ab25 100644 --- a/res/races/orc.xml +++ b/res/races/orc.xml @@ -1,5 +1,5 @@ - - + + diff --git a/res/races/troll.xml b/res/races/troll.xml index 3761e17ec..f151126fb 100644 --- a/res/races/troll.xml +++ b/res/races/troll.xml @@ -1,5 +1,5 @@ - - + + diff --git a/res/races/zombie.xml b/res/races/zombie.xml index 5d76a8557..faecf021d 100644 --- a/res/races/zombie.xml +++ b/res/races/zombie.xml @@ -1,8 +1,8 @@ - + diff --git a/res/ships.xml b/res/ships.xml index f5577c2f4..fbd6ce8e6 100644 --- a/res/ships.xml +++ b/res/ships.xml @@ -1,4 +1,4 @@ - + diff --git a/res/ships/boat.xml b/res/ships/boat.xml index c19d18529..28d48392f 100644 --- a/res/ships/boat.xml +++ b/res/ships/boat.xml @@ -1,4 +1,4 @@ - + diff --git a/res/terrains.xml b/res/terrains.xml index 3ccfa4606..f5786d42a 100644 --- a/res/terrains.xml +++ b/res/terrains.xml @@ -1,4 +1,4 @@ - + diff --git a/res/weapons.xml b/res/weapons.xml index 0cab11ad0..d0b508012 100644 --- a/res/weapons.xml +++ b/res/weapons.xml @@ -1,25 +1,25 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + diff --git a/s/build b/s/build index 2cf22b135..3f193a7bd 100755 --- a/s/build +++ b/s/build @@ -1,13 +1,13 @@ #!/bin/sh -ROOT=$(pwd) +ROOT=`pwd` while [ ! -d $ROOT/.git ]; do - ROOT=$(dirname $ROOT) + ROOT=`dirname $ROOT` done [ -z "$CC" ] && CC=clang [ -z "$BUILD" ] && BUILD=Debug -[ -z "$JOBS" ] && JOBS=$(nproc) +[ -z "$JOBS" ] && [ "" != "which nproc" ] && JOBS=`nproc` DISTCC=`which distcc` if [ ! -z "$DISTCC" ] ; then JOBS=`distcc -j` diff --git a/s/install b/s/install index 08d171849..a59c8aa46 100755 --- a/s/install +++ b/s/install @@ -2,12 +2,14 @@ ROOT=$(pwd) while [ ! -d $ROOT/.git ]; do ROOT=$(dirname $ROOT) - if [ "$ROOT" == "/" ; then + if [ "/" = "$ROOT" ]; then echo "could not find root, are you in the git repository?" exit fi done +DEST=$(dirname $ROOT)/server + MACHINE=`uname -m` [ -z "$CC" ] && [ ! -z `which gcc` ] && CC="gcc" [ -z "$CC" ] && [ ! -z `which tcc` ] && CC="tcc" @@ -17,3 +19,14 @@ BIN_DIR="build-$MACHINE-$CC-Debug" cd $ROOT/$BIN_DIR make install +[ -d $DEST/bin ] || mkdir -p $DEST/bin +install -v $ROOT/process/cron/*.cron $DEST/bin/ +programs="create-orders backup-eressea run-turn" +for prg in ${programs} ; do +install -v $ROOT/process/$prg $DEST/bin/ +done + +# install crontab, but only on the eressea server: +HOST=`hostname` + +[ "gruenbaer" = "$HOST" ] && crontab $ROOT/process/cron/crontab diff --git a/s/preview b/s/preview index 12752738f..157628f42 100755 --- a/s/preview +++ b/s/preview @@ -24,6 +24,7 @@ assert_dir $SOURCE cd $SOURCE git fetch || abort "failed to update source. do you have local changes?" [ -z $1 ] || git checkout $1 +git pull git submodule update s/build || abort "build failed." } @@ -80,10 +81,11 @@ ln -f $LIVE/data/$turn.dat data/ rm -rf reports mkdir -p reports -SERVER="$SOURCE/build-x86_64-gcc-Debug/eressea/eressea" +SUPP="$SOURCE/share/ubuntu-12_04.supp" +SERVER="$SOURCE/Debug/eressea/eressea" VALGRIND=$(which valgrind) if [ ! -z $VALGRIND ]; then -SERVER="$VALGRIND --leak-check=no $SERVER" +SERVER="$VALGRIND --suppressions=$SUPP --error-exitcode=1 --leak-check=no $SERVER" fi $SERVER -v$verbose -t$turn -re$game $SOURCE/scripts/run-turn.lua let turn=$turn+1 @@ -147,7 +149,7 @@ case "$1" in ;; "run") if [ $turn -eq 0 ]; then - [ -f $LIVE/turn ] || abort "missing turn file, and no turn specified" + [ -f $LIVE/turn ] || abort "missing turn file in $LIVE, and no turn specified" let turn=$(cat $LIVE/turn)-1 fi run diff --git a/s/runtests b/s/runtests index 1e7da54fd..3f95da595 100755 --- a/s/runtests +++ b/s/runtests @@ -1,4 +1,6 @@ #!/bin/bash +set -e + ROOT=$(pwd) while [ ! -d $ROOT/.git ]; do ROOT=$(dirname $ROOT) @@ -14,6 +16,8 @@ fi $ROOT/$BUILD/eressea/test_eressea cd $ROOT [ -e eressea.ini ] || ln -sf conf/eressea.ini -$ROOT/$BUILD/eressea/eressea -v0 sacripts/run-tests.lua +$ROOT/$BUILD/eressea/eressea -v0 scripts/run-tests.lua +$ROOT/$BUILD/eressea/eressea -v0 scripts/run-tests-e2.lua $ROOT/$BUILD/eressea/eressea -v0 scripts/run-tests-e3.lua + cd $OLDWPD diff --git a/s/setup b/s/setup index 1cb6a1867..0839d5b8f 100755 --- a/s/setup +++ b/s/setup @@ -91,7 +91,9 @@ ini_add lua install $SOURCE ini_add lua paths $SOURCE/scripts:$SOURCE/lunit ini_add lua rules $rules -ln -f $SOURCE/bin/eressea -ln -f $SOURCE/scripts/run-turn.lua -ln -f $SOURCE/scripts/reports.lua -ln -f $SOURCE/scripts/config.lua +echo 0 > turn +touch newfactions +ln -sf $SOURCE/bin/eressea +ln -sf $SOURCE/scripts/run-turn.lua +ln -sf $SOURCE/scripts/reports.lua +ln -sf $SOURCE/scripts/config.lua diff --git a/s/travis-build b/s/travis-build index c16211436..ad2c8607b 100755 --- a/s/travis-build +++ b/s/travis-build @@ -3,9 +3,10 @@ ROOT=`pwd` inifile() { +cd $ROOT if [ ! -e eressea.ini ]; then cp conf/eressea.ini . -build/iniparser/inifile eressea.ini add lua:paths lunit:scripts +$BUILD/iniparser/inifile eressea.ini add lua:paths lunit:scripts fi } diff --git a/scripts/config.lua b/scripts/config.lua index 1251c1e1c..8b61bcad2 100644 --- a/scripts/config.lua +++ b/scripts/config.lua @@ -4,5 +4,5 @@ if config.install then end package.path = package.path .. ';' .. path .. '/?.lua;' .. path .. '/?/init.lua' require 'eressea' -require 'eressea.xmlconf' -return require('eressea.rules') +require 'eressea.xmlconf' -- read xml data + diff --git a/scripts/eressea/e2/init.lua b/scripts/eressea/e2/init.lua index a23aa3216..581836147 100644 --- a/scripts/eressea/e2/init.lua +++ b/scripts/eressea/e2/init.lua @@ -13,5 +13,6 @@ return { require('eressea.ponnuki'), require('eressea.astral'), require('eressea.locales'), + require('eressea.jsreport'), require('eressea.ents') } diff --git a/scripts/eressea/embassy.lua b/scripts/eressea/embassy.lua index e4cd4b3fc..efbe248b7 100644 --- a/scripts/eressea/embassy.lua +++ b/scripts/eressea/embassy.lua @@ -25,7 +25,10 @@ function embassy.init() end function embassy.update() --- Muschelplateau + -- Muschelplateau + if home==nil then + return + end eressea.log.debug("updating embassies in " .. tostring(home)) local u for u in home.units do diff --git a/scripts/eressea/ents.lua b/scripts/eressea/ents.lua index 47cb3efff..c764d8e0a 100644 --- a/scripts/eressea/ents.lua +++ b/scripts/eressea/ents.lua @@ -1,7 +1,7 @@ local function create_ents(r, number) local f = get_faction(666) if f~=nil and number>0 then - u = unit.create(f, r, number) + u = unit.create(f, r, number, "ent") u.name = "Wütende Ents" u:set_skill("perception", 2) @@ -13,11 +13,21 @@ local function create_ents(r, number) return nil end +local function repair_ents(r) + for u in r.units do + if u.faction.id==666 and u.race == "undead" and u.name == "Wütende Ents" then + eressea.log.info("ent repair: " .. tostring(u)) + u.race = "ent" + end + end +end + local ents = {} function ents.update() local r for r in regions() do + repair_ents(r) if r:get_flag(0) then -- RF_CHAOTIC if r.terrain == "plain" and r:get_resource("tree")==0 then if math.random(3)==1 then diff --git a/scripts/eressea/jsreport.lua b/scripts/eressea/jsreport.lua new file mode 100644 index 000000000..0351efd12 --- /dev/null +++ b/scripts/eressea/jsreport.lua @@ -0,0 +1,22 @@ +local pkg = {} + +function pkg.init() + eressea.settings.set("feature.jsreport.enable", "1") +end + +function pkg.update() + local factions = { '777', '1wpy', 'd08a', 'hani', 'scaL' } + for _, id in ipairs(factions) do + local f = faction.get(id) + if f then + local o = f.options + local bit = (math.floor(o / 8) % 2) + if bit==0 then + eressea.log.info("enable JSON report for " .. tostring(f)) + f.options = o + 8 + end + end + end +end + +return pkg diff --git a/scripts/eressea/tests/attrib.lua b/scripts/eressea/tests/attrib.lua deleted file mode 100644 index 73d961d94..000000000 --- a/scripts/eressea/tests/attrib.lua +++ /dev/null @@ -1,53 +0,0 @@ -require "lunit" - -module("tests.eressea.attrib", package.seeall, lunit.testcase) - -function has_attrib(u, value) - for a in u.attribs do - if (a.data==value) then return true end - end - return false -end - -function test_attrib_global() - a = attrib.create('global', {}) - eressea.write_game('attrib.dat') - eressea.free_game() - eressea.read_game('attrib.dat') -end - -function test_attrib() - local r = region.create(0,0, "plain") - local f = faction.create("noreply@eressea.de", "human", "de") - local u = unit.create(f, r, 1) - local u2 = unit.create(f, r, 1) - data = { arr = { 'a', 'b', 'c' }, name = 'familiar', events = { die = 'familiar_died' }, data = { mage = u2 } } - a = { 'a' } - b = { 'a' } - uno = u.id - u2no = u2.id - a = attrib.create(u, 12) - a = attrib.create(u, "enno") - a = attrib.create(u, u2) - a = attrib.create(u, data) - eressea.write_game("attrib.dat") - eressea.free_game() - eressea.read_game("attrib.dat") - u = get_unit(uno) - u2 = get_unit(u2no) - assert_false(has_attrib(u, 42)) - assert_true(has_attrib(u, "enno")) - assert_true(has_attrib(u, 12)) - - for a in u.attribs do - x = a.data - if (type(x)=="table") then - assert_equal('a', x.arr[1]) - assert_equal('familiar', x.name) - assert_equal('familiar_died', x.events.die) - assert_equal(u2, x.data.mage) - break - end - end -end - diff --git a/scripts/eressea/tests/bson.lua b/scripts/eressea/tests/bson.lua deleted file mode 100644 index ec0966bcd..000000000 --- a/scripts/eressea/tests/bson.lua +++ /dev/null @@ -1,65 +0,0 @@ -require "lunit" - -module("tests.eressea.bson", package.seeall, lunit.testcase) - -function setup() - eressea.free_game() -end - -function test_bson_create() - local a = attrib.create("global", 12) - assert_not_equal(nil, a) - for a in attrib.get("global") do - assert_equal(a.data, 12) - end -end - -function test_illegal_arg() - local a = attrib.create(nil, 42) - assert_equal(nil, a) - a = attrib.create("fred", 42) - assert_equal(nil, a) -end - -function test_bson_readwrite() - local i, r = region.create(0, 0, "mountain") - attrib.create(r, 42) - i = eressea.write_game("test_read_write.dat") - assert_equal(0, i) - eressea.free_game() - r = get_region(0, 0) - assert_equal(nil, r) - i = eressea.read_game("test_read_write.dat") - assert_equal(0, i) - r = get_region(0, 0) - assert_not_equal(nil, r) - for a in attrib.get(r) do - assert_equal(a.data, 42) - end -end - -function test_bson() - local r = region.create(0, 0, "mountain") - local f = faction.create("noreply@eressea.de", "human", "de") - local u = unit.create(f, r, 1) - assert_not_equal(nil, u) - assert_not_equal(nil, r) - assert_not_equal(nil, f) - attrib.create(r, 1) - assert_equal(attrib.get(r)().data, 1) - attrib.create(u, 3) - assert_equal(attrib.get(u)().data, 3) - attrib.create(f, 5) - assert_equal(attrib.get(f)().data, 5) -end - -function test_bson_with_multiple_attribs() - local r = region.create(0, 0, "mountain") - attrib.create(r, { a=1}) - attrib.create(r, { a=5}) - local total = 0 - for a in attrib.get(r) do - total = total + a.data.a; - end - assert_equal(6, total) -end diff --git a/scripts/eressea/tests/castles.lua b/scripts/eressea/tests/castles.lua deleted file mode 100644 index 5bb506333..000000000 --- a/scripts/eressea/tests/castles.lua +++ /dev/null @@ -1,27 +0,0 @@ -require "lunit" - -module('tests.eressea.castles', package.seeall, lunit.testcase ) - -function setup() - eressea.free_game() -end - -function test_small_castles() - local r = region.create(0, 0, "plain") - local f1 = faction.create("noreply@eressea.de", "human", "de") - local u1 = unit.create(f1, r, 1) - local f2 = faction.create("noreply@eressea.de", "halfling", "de") - local u2 = unit.create(f2, r, 1) - u1:add_item("money", 10000) - - local b = building.create(r, "castle") - u2.building = b - u1.building = b - - b.owner = u2 - assert_equal("site", b:get_typename(7)) - assert_equal("fortification", b:get_typename(8)) - b.owner = u1 - assert_equal("site", b:get_typename(9)) - assert_equal("fortification", b:get_typename(10)) -end diff --git a/scripts/eressea/tests/config.lua b/scripts/eressea/tests/config.lua deleted file mode 100644 index b24da72bc..000000000 --- a/scripts/eressea/tests/config.lua +++ /dev/null @@ -1,39 +0,0 @@ -require "lunit" - -module("tests.eressea.config", package.seeall, lunit.testcase ) - -function setup() - eressea.free_game() -end - -function test_read_race() - local f - eressea.free_game() - f = faction.create("orc@example.com", "orc", "en") - assert_equal(nil, f) - assert_not_nil(eressea.config) - eressea.config.parse('{ "races": { "orc" : {}}}') - f = faction.create("orc@example.com", "orc", "en") - assert_not_nil(f) -end - -function test_read_ship() - local s - eressea.free_game() - s = ship.create(nil, "boat") - assert_equal(nil, s) - assert_not_nil(eressea.config) - conf = [[{ - "ships": { - "boat" : { - "construction" : { - "maxsize" : 20 - } - } - } - }]] - eressea.config.parse(conf); - s = ship.create(nil, "boat") - assert_not_nil(s) -end - diff --git a/scripts/eressea/tests/e3a.lua b/scripts/eressea/tests/e3a.lua deleted file mode 100644 index fc0031efb..000000000 --- a/scripts/eressea/tests/e3a.lua +++ /dev/null @@ -1,735 +0,0 @@ -require "lunit" - -module("tests.e3.e3features", package.seeall, lunit.testcase) - -function setup() - eressea.free_game() - eressea.settings.set("rules.economy.food", "4") -end - -function test_no_stealth() - local r = region.create(0,0, "plain") - local f = faction.create("noreply@eressea.de", "human", "de") - local u = unit.create(f, r, 1) - - u:set_skill("stealth", 1) - assert_equal(-1, u:get_skill("stealth")) - u:clear_orders() - u:add_order("LERNEN TARNUNG") - process_orders() - assert_equal(-1, u:get_skill("stealth")) -end - ---[[ -function test_analyze_magic() - local r1 = region.create(0,0, "plain") - local r2 = region.create(1,0, "plain") - local f = faction.create("noreply@eressea.de", "human", "de") - - local u = unit.create(f, r2, 1) - - u.race = "elf" - u:set_skill("magic", 6) - u.magic = "gwyrrd" - u.aura = 60 - u:add_spell("analyze_magic") - u:clear_orders() - u:add_order("Zaubere stufe 2 'Magie analysieren' REGION 1,0") - process_orders() -end -]]-- - -function test_seecast() - local r = region.create(0,0, "plain") - for i = 1,10 do - -- this prevents storms (only high seas have storms) - region.create(i, 1, "plain") - end - for i = 1,10 do - region.create(i, 0, "ocean") - end - local f = faction.create("noreply@eressea.de", "human", "de") - local s1 = ship.create(r, "cutter") - local u1 = unit.create(f, r, 2) - u1:set_skill("sailing", 3) - u1:add_item("money", 1000) - u1.ship = s1 - local u2 = unit.create(f, r, 1) - u2.race = "elf" - u2:set_skill("magic", 6) - u2.magic = "gwyrrd" - u2.aura = 60 - u2.ship = s1 - u2:add_spell("stormwinds") - update_owners() - u2:clear_orders() - u2:add_order("Zaubere stufe 2 'Beschwoere einen Sturmelementar' " .. itoa36(s1.id)) - u1:clear_orders() - u1:add_order("NACH O O O O") - process_orders() - assert_equal(4, u2.region.x) - - u2:clear_orders() - u2:add_order("Zaubere stufe 2 'Beschwoere einen Sturmelementar' " .. itoa36(s1.id)) - u1:clear_orders() - u1:add_order("NACH O O O O") - process_orders() - assert_equal(8, u2.region.x) -end - -local function use_tree(terrain) - local r = region.create(0,0, terrain) - local f = faction.create("noreply@eressea.de", "human", "de") - local u1 = unit.create(f, r, 5) - r:set_resource("tree", 0) - u1:add_item("xmastree", 1) - u1:clear_orders() - u1:add_order("BENUTZEN 1 Weihnachtsbaum") - process_orders() - return r -end - -function test_xmas2009() - local r = region.create(0,0, "plain") - local f = faction.create("noreply@eressea.de", "human", "de") - local u1 = unit.create(f, r, 1) - process_orders() - xmas2009() - assert_equal("xmastree", f.items()) -end - -function test_xmastree() - local r - r = use_tree("ocean") - assert_equal(0, r:get_resource("tree")) - eressea.free_game() - r = use_tree("plain") - assert_equal(10, r:get_resource("tree")) -end - -function test_fishing() - eressea.settings.set("rules.economy.food", "0") - local r = region.create(0,0, "ocean") - local r2 = region.create(1,0, "plain") - local f = faction.create("noreply@eressea.de", "human", "de") - local s1 = ship.create(r, "cutter") - local u1 = unit.create(f, r, 3) - u1.ship = s1 - u1:set_skill("sailing", 10) - u1:add_item("money", 100) - u1:clear_orders() - u1:add_order("NACH O") - update_owners() - - process_orders() - assert_equal(r2, u1.region) - assert_equal(90, u1:get_item("money")) - - u1:clear_orders() - u1:add_order("NACH W") - - process_orders() - assert_equal(r, u1.region) - assert_equal(60, u1:get_item("money")) -end - -function test_ship_capacity() - eressea.settings.set("rules.ship.drifting", "0") - eressea.settings.set("rules.ship.storms", "0") - local r = region.create(0,0, "ocean") - region.create(1,0, "ocean") - local r2 = region.create(2,0, "ocean") - local f = faction.create("noreply@eressea.de", "human", "de") - local f2 = faction.create("noreply@eressea.de", "goblin", "de") - - -- u1 is at the limit and moves - local s1 = ship.create(r, "cutter") - local u1 = unit.create(f, r, 5) - u1.ship = s1 - u1:set_skill("sailing", 10) - u1:add_item("sword", 55) - u1:clear_orders() - u1:add_order("NACH O O") - - -- u2 has too many people - local s2 = ship.create(r, "cutter") - local u2 = unit.create(f, r, 6) - u2.ship = s2 - u2:set_skill("sailing", 10) - u2:clear_orders() - u2:add_order("NACH O O") - - -- u3 has goblins, they weigh 40% less - local s3 = ship.create(r, "cutter") - local u3 = unit.create(f2, r, 8) - u3.ship = s3 - u3:set_skill("sailing", 10) - u3:add_item("sword", 55) - u3:clear_orders() - u3:add_order("NACH O O") - - -- u4 has too much stuff - local s4 = ship.create(r, "cutter") - local u4 = unit.create(f, r, 5) - u4.ship = s4 - u4:set_skill("sailing", 10) - u4:add_item("sword", 56) - u4:clear_orders() - u4:add_order("NACH O O") - - update_owners() - process_orders() - if r2~=u1.region then - print(get_turn(), u1, u1.faction) - write_reports() - end - assert_equal(r2, u1.region) - assert_not_equal(r2.id, u2.region.id) - if r2~=u3.region then - print(get_turn(), u3, u3.faction) - write_reports() - end - assert_equal(r2, u3.region) - assert_not_equal(r2.id, u4.region.id) -end - -function test_owners() - local r = region.create(0, 0, "plain") - local f1 = faction.create("noreply@eressea.de", "human", "de") - local u1 = unit.create(f1, r, 1) - local f2 = faction.create("noreply@eressea.de", "human", "de") - local u2 = unit.create(f2, r, 1) - local u3 = unit.create(f2, r, 1) - - local b3 = building.create(r, "castle") - b3.size = 2 - u3.building = b3 - local b1 = building.create(r, "castle") - b1.size = 1 - u1.building = b1 - local b2 = building.create(r, "castle") - b2.size = 2 - u2.building = b2 - - update_owners() - assert(r.owner==u3.faction) - b1.size=3 - b2.size=3 - update_owners() - assert(r.owner==u2.faction) - b1.size=4 - update_owners() - assert(r.owner==u1.faction) -end - -function test_taxes() - local r = region.create(0, 0, "plain") - r:set_resource("peasant", 1000) - r:set_resource("money", 5000) - local f = faction.create("noreply@eressea.de", "human", "de") - local u = unit.create(f, r, 1) - u:clear_orders() - u:add_order("LERNE Holzfaellen") -- do not work - local b = building.create(r, "watch") - b.size = 10 - u.building = b - update_owners() - assert_equal(1, r.morale) - process_orders() - assert_equal(1, r.morale) - assert_equal(25, u:get_item("money")) -end - -function test_region_owner_cannot_leave_castle() - eressea.settings.set("rules.move.owner_leave", "1") - local r = region.create(0, 0, "plain") - local f = faction.create("noreply@eressea.de", "human", "de") - f.id = 42 - local b1 = building.create(r, "castle") - b1.size = 10 - local b2 = building.create(r, "lighthouse") - b2.size = 10 - local u = unit.create(f, r, 1) - u.building = b1 - u:add_item("money", u.number * 100) - u:clear_orders() - u:add_order("BETRETE BURG " .. itoa36(b2.id)) - process_orders() - init_reports() - write_report(u.faction) - assert_equal(b1, u.building, "region owner has left the building") -- region owners may not leave -end - -function test_market() - -- if i am the only trader around, i should be getting all the herbs from all 7 regions - local herb_multi = 500 -- from rc_herb_trade() - local r, idx - local herbnames = { 'h0', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8' } - idx = 1 - for x = -1, 1 do for y = -1, 1 do - r = region.create(x, y, "plain") - r:set_resource("peasant", herb_multi * 9 + 50) -- 10 herbs per region - r.herb = herbnames[idx] - idx = idx+1 - end end - r = get_region(0, 0) - local b = building.create(r, "market") - b.size = 10 - local f = faction.create("noreply@eressea.de", "human", "de") - f.id = 42 - local u = unit.create(f, r, 1) - u.building = b - u:add_item("money", u.number * 10000) - for i = 0, 5 do - local rn = r:next(i) - end - b.working = true - eressea.process.markets() - u:add_item("money", -u:get_item("money")) -- now we only have herbs - local len = 0 - for i in u.items do - len = len + 1 - end - assert_not_equal(0, len, "trader did not get any herbs") - for idx, name in pairs(herbnames) do - local n = u:get_item(name) - if n>0 then - assert_equal(10, n, 'trader did not get exaxtly 10 herbs') - end - end -end - -function test_market_gives_items() - local r - for x = -1, 1 do for y = -1, 1 do - r = region.create(x, y, "plain") - r:set_resource("peasant", 5000) - end end - r = get_region(0, 0) - local b = building.create(r, "market") - b.size = 10 - local f = faction.create("noreply@eressea.de", "human", "de") - f.id = 42 - local u = unit.create(f, r, 1) - u.building = b - u:add_item("money", u.number * 10000) - for i = 0, 5 do - local rn = r:next(i) - end - process_orders() - local len = 0 - for i in u.items do - len = len + 1 - end - assert(len>1) -end - -function test_spells() - local r = region.create(0, 0, "plain") - local f = faction.create("noreply@eressea.de", "human", "de") - local u = unit.create(f, r, 1) - u.race = "elf" - u:clear_orders() - u:add_item("money", 10000) - u:set_skill("magic", 5) - u:add_order("LERNE MAGIE Illaun") - process_orders() - local sp - local nums = 0 - if f.spells~=nil then - for sp in f.spells do - nums = nums + 1 - end - assert(nums>0) - for sp in u.spells do - nums = nums - 1 - end - assert(nums==0) - elseif u.spells~=nil then - for sp in u.spells do - nums = nums + 1 - end - assert(nums>0) - end -end - -function test_alliance() - local r = region.create(0, 0, "plain") - local f1 = faction.create("noreply@eressea.de", "human", "de") - local u1 = unit.create(f1, r, 1) - u1:add_item("money", u1.number * 100) - local f2 = faction.create("info@eressea.de", "human", "de") - local u2 = unit.create(f2, r, 1) - u2:add_item("money", u2.number * 100) - assert(f1.alliance==nil) - assert(f2.alliance==nil) - u1:clear_orders() - u2:clear_orders() - u1:add_order("ALLIANZ NEU pink") - u1:add_order("ALLIANZ EINLADEN " .. itoa36(f2.id)) - u2:add_order("ALLIANZ BEITRETEN pink") - process_orders() - assert(f1.alliance~=nil) - assert(f2.alliance~=nil) - assert(f2.alliance==f1.alliance) - u1:clear_orders() - u2:clear_orders() - u1:add_order("ALLIANZ KOMMANDO " .. itoa36(f2.id)) - process_orders() - assert(f1.alliance~=nil) - assert(f2.alliance~=nil) - assert(f2.alliance==f1.alliance) - for f in f1.alliance.factions do - assert_true(f.id==f1.id or f.id==f2.id) - end - u1:clear_orders() - u2:clear_orders() - u2:add_order("ALLIANZ AUSSTOSSEN " .. itoa36(f1.id)) - process_orders() - assert(f1.alliance==nil) - assert(f2.alliance~=nil) - u1:clear_orders() - u2:clear_orders() - u2:add_order("ALLIANZ NEU zing") - u1:add_order("ALLIANZ BEITRETEN zing") -- no invite! - process_orders() - assert(f1.alliance==nil) - assert(f2.alliance~=nil) - u1:clear_orders() - u2:clear_orders() - u1:add_order("ALLIANZ NEU zack") - u1:add_order("ALLIANZ EINLADEN " .. itoa36(f2.id)) - u2:add_order("ALLIANZ BEITRETEN zack") - process_orders() - assert(f1.alliance==f2.alliance) - assert(f2.alliance~=nil) -end - -function test_canoe_passes_through_land() - local f = faction.create("noreply@eressea.de", "human", "de") - local src = region.create(0, 0, "ocean") - local land = region.create(1, 0, "plain") - region.create(2, 0, "ocean") - local dst = region.create(3, 0, "ocean") - local sh = ship.create(src, "canoe") - local u1 = unit.create(f, src, 1) - local u2 = unit.create(f, src, 1) - u1.ship = sh - u2.ship = sh - u1:set_skill("sailing", 10) - u1:clear_orders() - u1:add_order("NACH O O O") - process_orders() - assert_equal(land, u2.region, "canoe did not stop at coast") - u1:add_order("NACH O O O") - process_orders() - assert_equal(dst, sh.region, "canoe could not leave coast") - assert_equal(dst, u1.region, "canoe could not leave coast") - assert_equal(dst, u2.region, "canoe could not leave coast") -end - -function test_give_50_percent_of_money() - local r = region.create(0, 0, "plain") - local u1 = unit.create(faction.create("noreply@eressea.de", "human", "de"), r, 1) - local u2 = unit.create(faction.create("noreply@eressea.de", "orc", "de"), r, 1) - u1.faction.age = 10 - u2.faction.age = 10 - u1:add_item("money", 500) - u2:add_item("money", 500) - local m1, m2 = u1:get_item("money"), u2:get_item("money") - u1:clear_orders() - u1:add_order("GIB " .. itoa36(u2.id) .. " 221 Silber") - u2:clear_orders() - u2:add_order("LERNEN Hiebwaffen") - process_orders() - assert_equal(m1, u1:get_item("money")) - assert_equal(m2, u2:get_item("money")) - - m1, m2 = u1:get_item("money"), u2:get_item("money") - u1:clear_orders() - u1:add_order("GIB " .. itoa36(u2.id) .. " 221 Silber") - u2:clear_orders() - u2:add_order("HELFEN " .. itoa36(u1.faction.id) .. " GIB") - u2:add_item("horse", 100) - u2:add_order("GIB 0 ALLES PFERD") - local h = r:get_resource("horse") - process_orders() - assert_true(r:get_resource("horse")>=h+100) - assert_equal(m1-221, u1:get_item("money")) - assert_equal(m2+110, u2:get_item("money")) -end - -function test_give_100_percent_of_items() - r = region.create(0, 0, "plain") - local u1 = unit.create(faction.create("noreply@eressea.de", "human", "de"), r, 1) - local u2 = unit.create(faction.create("noreply@eressea.de", "orc", "de"), r, 1) - u1.faction.age = 10 - u2.faction.age = 10 - u1:add_item("money", 500) - u1:add_item("log", 500) - local m1, m2 = u1:get_item("log"), u2:get_item("log") - u1:clear_orders() - u1:add_order("GIB " .. itoa36(u2.id) .. " 332 Holz") - u2:clear_orders() - u2:add_order("LERNEN Hiebwaffen") - u2:add_order("HELFEN " .. itoa36(u1.faction.id) .. " GIB") - process_orders() - assert_equal(m1-332, u1:get_item("log")) - assert_equal(m2+332, u2:get_item("log")) -end - -function test_cannot_give_person() - local r = region.create(0, 0, "plain") - local f1 = faction.create("noreply@eressea.de", "human", "de") - local f2 = faction.create("noreply@eressea.de", "human", "de") - local u1 = unit.create(f1, r, 10) - local u2 = unit.create(f2, r, 10) - u1.faction.age = 10 - u2.faction.age = 10 - u1:add_item("money", 500) - u2:add_item("money", 500) - u2:clear_orders() - u2:add_order("GIB ".. itoa36(u1.id) .. " 1 PERSON") - u2:add_order("HELFE ".. itoa36(f1.id) .. " GIB") - u1:add_order("HELFE ".. itoa36(f2.id) .. " GIB") - process_orders() - assert_equal(10, u2.number) - assert_equal(10, u1.number) -end - -function test_cannot_give_unit() - local r = region.create(0, 0, "plain") - local f1 = faction.create("noreply@eressea.de", "human", "de") - local f2 = faction.create("noreply@eressea.de", "human", "de") - local u1 = unit.create(f1, r, 10) - local u2 = unit.create(f2, r, 10) - u1.faction.age = 10 - u2.faction.age = 10 - u1:add_item("money", 500) - u2:add_item("money", 500) - u2:clear_orders() - u2:add_order("GIB ".. itoa36(u1.id) .. " EINHEIT") - u2:add_order("HELFE ".. itoa36(f1.id) .. " GIB") - u1:add_order("HELFE ".. itoa36(f2.id) .. " GIB") - process_orders() - assert_not_equal(u2.faction.id, u1.faction.id) -end - -function test_guard_by_owners() - -- http://bugs.eressea.de/view.php?id=1756 - local r = region.create(0,0, "mountain") - local f1 = faction.create("noreply@eressea.de", "human", "de") - f1.age=20 - local f2 = faction.create("noreply@eressea.de", "human", "de") - f2.age=20 - local u1 = unit.create(f1, r, 1) - local b = building.create(r, "castle") - b.size = 10 - u1.building = b - u1:add_item("money", 100) - - local u2 = unit.create(f2, r, 1) - u2:add_item("money", 100) - u2:set_skill("mining", 3) - u2:clear_orders() - u2:add_order("MACHEN EISEN") - - process_orders() - local iron = u2:get_item("iron") - process_orders() - assert_equal(iron, u2:get_item("iron")) -end - -function test_market_action() - local f = faction.create("noreply@eressea.de", "human", "de") - local x, y, r - for x=0,2 do - for y=0,2 do - r = region.create(x, y, "plain") - r.luxury = "balm" - r.herb = "h2" - r:set_resource("peasant", 5000) - end - end - r = get_region(1, 1) - local u = unit.create(f, r, 1) - b = building.create(r, "market") - b.size = 10 - u.building = b - update_owners() - for r in regions() do - market_action(r) - end - assert_equal(35, u:get_item("balm")) - assert_equal(70, u:get_item("h2")) -end - -local function setup_packice(x, onfoot) - local f = faction.create("noreply@eressea.de", "human", "de") - local plain = region.create(0,0, "plain") - local ice = region.create(1,0, "packice") - local ocean = region.create(2,0, "ocean") - local u = unit.create(f, get_region(x, 0), 2) - if not onfoot then - local s = ship.create(u.region, "cutter") - u:set_skill("sailing", 3) - u.ship = s - end - u:add_item("money", 400) - - return u -end - -function test_no_sailing_through_packice() - local u = setup_packice(0) - u:clear_orders() - u:add_order("NACH O O") - process_orders() - assert_equal(0, u.region.x) -end - -function test_can_sail_from_packice_to_ocean() - local u = setup_packice(1) - - u:clear_orders() - u:add_order("NACH W") - process_orders() - assert_equal(1, u.region.x) - - u:clear_orders() - u:add_order("NACH O") - process_orders() - assert_equal(2, u.region.x) -end - -function test_can_sail_into_packice() - local u = setup_packice(2) - u:clear_orders() - u:add_order("NACH W W") - process_orders() - assert_equal(1, u.region.x) -end - -function test_can_walk_into_packice() - local u = setup_packice(0, true) - u:clear_orders() - u:add_order("NACH O") - process_orders() - assert_equal(1, u.region.x) -end - -function test_cannot_walk_into_ocean() - local u = setup_packice(1, true) - u:clear_orders() - u:add_order("NACH O") - process_orders() - assert_equal(1, u.region.x) -end - -function test_p2() - local f = faction.create("noreply@eressea.de", "human", "de") - local r = region.create(0, 0, "plain") - local u = unit.create(f, r, 1) - r:set_resource("tree", 0) - u:clear_orders() - u:add_order("BENUTZE 'Wasser des Lebens'") - u:add_item("p2", 1) - u:add_item("log", 10) - u:add_item("mallorn", 10) - process_orders() - assert_equal(5, r:get_resource("tree")) - assert_equal(0, u:get_item("p2")) - assert_equal(15, u:get_item("log") + u:get_item("mallorn")) -end - -function test_p2_move() - -- http://bugs.eressea.de/view.php?id=1855 - local f = faction.create("noreply@eressea.de", "human", "de") - local r = region.create(0, 0, "plain") - region.create(1, 0, "plain") - local u = unit.create(f, r, 1) - r:set_resource("tree", 0) - u:clear_orders() - u:add_order("BENUTZE 'Wasser des Lebens'") - u:add_order("NACH OST") - u:add_item("horse", 1) - u:add_item("p2", 1) - u:add_item("log", 1) - u:add_item("mallorn", 1) - process_orders() - assert_equal(1, u.region.x) - assert_equal(1, r:get_resource("tree")) -end - -function disabled_test_bug_1738_build_castle_e3() - local r = region.create(0, 0, "plain") - local f = faction.create("bug_1738@eressea.de", "human", "de") - - local c = building.create(r, "castle") - c.size = 228 - - local u1 = unit.create(f, r, 1) - u1:set_skill("building", 5) - u1:add_item("stone", 10000) - - local u2 = unit.create(f, r, 32) - u2:set_skill("building", 3) - u2:add_item("stone", 10000) - - u1:clear_orders() - u1:add_order("MACHE BURG " .. itoa36(c.id)) - -- castle now has size 229. - u2:clear_orders() - u2:add_order("MACHE BURG " .. itoa36(c.id)) - -- 32 * 3 makes 96 skill points. - -- from size 229 to size 250 needs 21 * 3 = 63 points, rest 33. - -- 33/4 makes 8 points, resulting size is 258. - - process_orders() - --[[ - init_reports() - write_report(f) - ]]-- - -- resulting size should be 250 because unit 2 - -- does not have the needed minimum skill. - assert_equal(c.size, 250) -end - -function test_golem_use_four_iron() - local r0 = region.create(0, 0, "plain") - local f1 = faction.create("noreply@eressea.de", "halfling", "de") - local u1 = unit.create(f1, r0, 3) - u1.race = "irongolem" - u1:set_skill("weaponsmithing", 1) - u1:set_skill("armorer", 1) - u1:clear_orders() - u1:add_order("Mache 4 Turmschild") - - process_orders() - - assert_equal(2, u1.number) - assert_equal(4, u1:get_item("towershield")) -end - -function test_building_owner_can_enter_ship() - local r1 = region.create(1, 2, "plain") - local f1 = faction.create("noreply@tteessttiinngg.de", "human", "de") - local b1 = building.create(r1, "castle") - b1.size = 10 - local s1 = ship.create(r1, "cutter") - - local u1 = unit.create(f1, r1, 10) - u1.building = b1 - u1:add_item("money", u1.number * 100) - u1:clear_orders() - u1:add_order("VERLASSEN") - u1:add_order("BETRETE SCHIFF " .. itoa36(s1.id)) - - local u2 = unit.create(f1, r1, 10) - u2.ship = s1 - u2:add_item("money", u1.number * 100) - u2:clear_orders() - process_orders() - assert_equal(s1, u1.ship) - assert_equal(null, u1.building, "owner of the building can not go into a ship") -end diff --git a/scripts/eressea/tests/init.lua b/scripts/eressea/tests/init.lua deleted file mode 100644 index d25bddb9f..000000000 --- a/scripts/eressea/tests/init.lua +++ /dev/null @@ -1,16 +0,0 @@ --- require 'eressea.tests.spells' -require 'eressea.tests.common' -require 'eressea.tests.stealth' --- require 'eressea.tests.spells-e3' --- require 'eressea.tests.spells-e2' -require 'eressea.tests.settings' --- require 'eressea.tests.morale' --- require 'eressea.tests.orders' --- require 'eressea.tests.eressea' --- require 'eressea.tests.e3a' --- require 'eressea.tests.config' --- require 'eressea.tests.common' -require 'eressea.tests.castles' -require 'eressea.tests.bindings' --- require 'eressea.tests.bson' --- require 'eressea.tests.attrib' diff --git a/scripts/eressea/tests/morale.lua b/scripts/eressea/tests/morale.lua deleted file mode 100644 index 88b451f1d..000000000 --- a/scripts/eressea/tests/morale.lua +++ /dev/null @@ -1,179 +0,0 @@ -require "lunit" - -module("tests.eressea.morale", package.seeall, lunit.testcase ) - -function setup() - eressea.game.reset() - eressea.settings.set('rules.region_owners', '1') -end - -function test_when_owner_returns_morale_drops_only_2() - local r = region.create(0, 0, "plain") - assert_equal(1, r.morale) - local f1 = faction.create("noreply@eressea.de", "human", "de") - local u1 = unit.create(f1, r, 1) - u1:add_item("money", 10000) - local b = building.create(r, "castle") - b.size = 50 - - set_turn(get_turn()+10) - f1.lastturn=get_turn() - u1.building = b - update_owners() - r.morale = 6 - u1.building = nil - process_orders() - assert_equal(5, r.morale) -- no owner, fall by 1 - u1.building = b - update_owners() - set_key("test", 42) - process_orders() - assert_equal(3, r.morale) -- new owner, fall by 2 -end - -function test_morale_alliance() - local r = region.create(0, 0, "plain") - assert_equal(1, r.morale) - local f1 = faction.create("noreply@eressea.de", "human", "de") - local u1 = unit.create(f1, r, 1) - u1:add_item("money", 10000) - local f2 = faction.create("noreply@eressea.de", "human", "de") - local u2 = unit.create(f2, r, 1) - u2:add_item("money", 10000) - local f3 = faction.create("noreply@eressea.de", "human", "de") - local u3 = unit.create(f3, r, 1) - u3:add_item("money", 10000) - - local al = alliance.create(42, "Die Antwoord") - f1.alliance = al; - f2.alliance = al; - - local b = building.create(r, "castle") - b.size = 50 - u1.building = b - u2.building = b - u3.building = b - update_owners() - r.morale = 6 - - local function run_a_turn() - process_orders() - f1.lastturn=get_turn() - f2.lastturn=get_turn() - f3.lastturn=get_turn() - end - - -- just checking everything's okay after setup. - run_a_turn() - assert_equal(6, r.morale) - - -- change owner, new owner is in the same alliance - u1.building = nil - run_a_turn() - assert_equal(4, r.morale) - - -- change owner, new owner is not in the same alliance - u2.building = nil - run_a_turn() - assert_equal(0, r.morale) -end - -function test_morale_change() - local r = region.create(0, 0, "plain") - assert_equal(1, r.morale) - local f1 = faction.create("noreply@eressea.de", "human", "de") - local u1 = unit.create(f1, r, 1) - u1:add_item("money", 10000) - local f2 = faction.create("noreply@eressea.de", "human", "de") - local u2 = unit.create(f2, r, 1) - u2:add_item("money", 10000) - - local AVG_STEP = 6 - local b = building.create(r, "castle") - b.size = 10 - u1.building = b - - local function run_a_turn() - process_orders() - f1.lastturn=get_turn() - f2.lastturn=get_turn() - end - - -- reinhardt-regel: nach 2*AVG_STEP ist moral mindestens einmal gestiegen. - update_owners() - assert_not_equal(r.owner, nil) - for i=1,AVG_STEP*2 do - run_a_turn() - assert_not_equal(r.owner, nil) - end - assert_not_equal(1, r.morale) - - -- regel: moral ist nie hoeher als 2 punkte ueber burgen-max. - for i=1,AVG_STEP*4 do - run_a_turn() - end - assert_equal(4, r.morale) - - -- auch mit herrscher faellt moral um 1 pro woche, wenn moral > burgstufe - r.morale = 6 - run_a_turn() - assert_equal(5, r.morale) - run_a_turn() - assert_equal(4, r.morale) - run_a_turn() - assert_equal(4, r.morale) - - -- regel: ohne herrscher fllt die moral jede woche um 1 punkt, bis sie 1 erreicht - u1.building = nil - update_owners() - run_a_turn() - assert_equal(3, r.morale) - run_a_turn() - assert_equal(2, r.morale) - run_a_turn() - assert_equal(1, r.morale) - run_a_turn() - assert_equal(1, r.morale) - - -- ohne herrscher ndert sich auch beschissene Moral nicht: - r.morale = 0 - run_a_turn() - assert_equal(0, r.morale) -end - -function test_morale_old() - local r = region.create(0, 0, "plain") - assert_equal(1, r.morale) - local f1 = faction.create("first@eressea.de", "human", "de") - local u1 = unit.create(f1, r, 1) - local f2 = faction.create("second@eressea.de", "human", "de") - local u2 = unit.create(f2, r, 1) - - local b = building.create(r, "castle") - b.size = 10 - u1.building = b - u2.building = b - update_owners() - assert_equal(1, r.morale) - r.morale = 5 - assert_equal(u1.faction, r.owner) - u1:clear_orders() - u1:add_order("GIB " .. itoa36(u2.id) .. " KOMMANDO") - process_orders() - u1:clear_orders() - assert_equal(r.owner, u2.faction) - assert_equal(3, r.morale) -- 5-MORALE_TRANSFER - for u in r.units do - if u.faction.id==u2.faction.id then - u.building = nil - end - end - update_owners() - assert_equal(r.owner, u1.faction) - assert_equal(0, r.morale) -end - -function test_no_uruk() - local f1 = faction.create("noreply@eressea.de", "uruk", "de") - assert_equal(f1.race, "orc") -end diff --git a/scripts/eressea/tests/settings.lua b/scripts/eressea/tests/settings.lua deleted file mode 100644 index a454a1152..000000000 --- a/scripts/eressea/tests/settings.lua +++ /dev/null @@ -1,13 +0,0 @@ -require "lunit" - -module("tests.eressea.settings", package.seeall, lunit.testcase ) - -function setup() - eressea.free_game() -end - -function test_settings() - assert_equal(nil, eressea.settings.get("foo")) - eressea.settings.set("foo", "bar") - assert_equal("bar", eressea.settings.get("foo")) -end diff --git a/scripts/eressea/tests/spells-e3.lua b/scripts/eressea/tests/spells-e3.lua deleted file mode 100644 index 44eda4e0f..000000000 --- a/scripts/eressea/tests/spells-e3.lua +++ /dev/null @@ -1,47 +0,0 @@ -require "lunit" - -module("eressea.tests.spells.e3", package.seeall, lunit.testcase) - -function setup() - eressea.free_game() - eressea.settings.set("magic.fumble.enable", "0") - eressea.settings.set("nmr.removenewbie", "0") - eressea.settings.set("nmr.timeout", "0") - eressea.settings.set("rules.peasants.growth", "0") -end - -function test_blessedharvest_lasts_n_turn() - eressea.free_game() - local r = region.create(0, 0, "plain") - local f = faction.create("noreply@eressea.de", "halfling", "de") - local u = unit.create(f, r) - local err = 0 - r:set_resource("peasant", 100) - r:set_resource("money", 0) - u:add_item("money", 1000) - u.magic = "gwyrrd" - u.race = "dwarf" - u:set_skill("magic", 20) - u.aura = 200 - err = err + u:add_spell("raindance") - err = err + u:add_spell("blessedharvest") - assert_equal(0, err) - - u:clear_orders() - u:add_order("ZAUBERE STUFE 3 Regentanz") - assert_equal(0, r:get_resource("money"), 0) - - local m = 0 - local p = 100 - - process_orders() - assert_equal(200, r:get_resource("money")) - u:clear_orders() - u:add_order("ARBEITEN") - process_orders() - process_orders() - process_orders() - assert_equal(800, r:get_resource("money")) - process_orders() - assert_equal(900, r:get_resource("money")) -end diff --git a/scripts/eressea/wedding.lua b/scripts/eressea/wedding.lua index f5575428b..da0c60eb1 100644 --- a/scripts/eressea/wedding.lua +++ b/scripts/eressea/wedding.lua @@ -45,7 +45,7 @@ function wedding.update() if peacegate and hellgate then wedding_exchange(peacegate, hellgate) else - eressea.log.error("hellgate or peacegate not found!", hellgate, peacegate) + eressea.log.error("hellgate or peacegate not found!") end end diff --git a/scripts/eressea/xmas2004.lua b/scripts/eressea/xmas2004.lua index 9b32d7a33..79d2b0665 100644 --- a/scripts/eressea/xmas2004.lua +++ b/scripts/eressea/xmas2004.lua @@ -1,18 +1,11 @@ function use_snowman(u, amount) - local have = u:get_item("snowman") - if have0 and u.region.terrain == "glacier" then - local man = unit.create(u.faction, u.region) - man.race = "snowman" - man.number = amount - if u:add_item("snowman", -amount)~= nil then - return -1 - end - return 0 - end - return -4 + if amount>0 and u.region.terrain == "glacier" then + local man = unit.create(u.faction, u.region) + man.race = "snowman" + man.number = amount + return amount + end + return -4 end local self = {} diff --git a/scripts/eressea/xmas2005.lua b/scripts/eressea/xmas2005.lua index df774cfef..9bc0ac723 100644 --- a/scripts/eressea/xmas2005.lua +++ b/scripts/eressea/xmas2005.lua @@ -11,8 +11,7 @@ function use_stardust(u, amount) u.region:set_resource("peasant", p) local msg = usepotion_message(u, "stardust") msg:send_region(u.region) - u:use_pooled("stardust", amount) - return 0 + return amount end local self = {} diff --git a/scripts/eressea/xmas2006.lua b/scripts/eressea/xmas2006.lua index fb1eaf476..85a8b3d98 100644 --- a/scripts/eressea/xmas2006.lua +++ b/scripts/eressea/xmas2006.lua @@ -1,11 +1,10 @@ function use_xmastree(u, amount) u.region:set_key("xm06", true) - u:use_pooled("xmastree", amount) local msg = message.create("usepotion") msg:set_unit("unit", u) msg:set_resource("potion", "xmastree") msg:send_region(u.region) - return 0 + return amount end local self = {} diff --git a/scripts/eressea/xmas2009.lua b/scripts/eressea/xmas2009.lua index 90fdc6e64..64bcd7762 100644 --- a/scripts/eressea/xmas2009.lua +++ b/scripts/eressea/xmas2009.lua @@ -1,14 +1,15 @@ function use_xmastree(u, amount) if u.region.herb~=nil then + -- TODO: else? local trees = u.region:get_resource("tree") u.region:set_resource("tree", 10+trees) - u:use_pooled("xmastree", amount) local msg = message.create("usepotion") msg:set_unit("unit", u) msg:set_resource("potion", "xmastree") msg:send_region(u.region) - return 0 + return amount end + return 0 end local xmas = {} diff --git a/scripts/eressea/xmlconf.lua b/scripts/eressea/xmlconf.lua index 8ddd09539..9d87f3f3e 100644 --- a/scripts/eressea/xmlconf.lua +++ b/scripts/eressea/xmlconf.lua @@ -2,9 +2,8 @@ local confdir = 'conf/' if config.install then confdir = config.install .. '/' .. confdir end -rules='' if config.rules then - rules = config.rules .. '/' + local rules = config.rules .. '/' + assert(0 == read_xml(confdir .. rules .. 'config.xml', confdir .. rules .. 'catalog.xml'), "could not load XML data, did you compile with LIBXML2 ?") + assert(0 == eressea.config.read(rules .. 'config.json', confdir), "could not read JSON data") end -read_xml(confdir .. rules .. 'config.xml', confdir .. rules .. 'catalog.xml') -eressea.config.read(rules .. 'config.json', confdir) diff --git a/scripts/newplayer.lua b/scripts/newplayer.lua new file mode 100644 index 000000000..45df076d6 --- /dev/null +++ b/scripts/newplayer.lua @@ -0,0 +1,95 @@ +dofile("config.lua") +p = require("populate") + +local function read_players() +-- return {{ email = "noreply@mailinator.com", race = "dwarf", lang = "de" }} + local players = {} + local input = io.open("newfactions", "r") + while input do + local str = input:read("*line") + if str==nil then break end + local email, race, lang = str:match("([^ ]*) ([^ ]*) ([^ ]*)") + if string.char(string.byte(email, 1))~='#' then + table.insert(players, { race = race, lang = lang, email = email }) + end + end + return players +end + +local function seed(r, email, race, lang) + local f = faction.create(email, race, lang) + local u = unit.create(f, r) + equip_unit(u, "new_faction") + equip_unit(u, "first_unit") + equip_unit(u, "first_" .. race, 7) -- disable old callbacks + unit.create(f, r, 5):set_skill("mining", 30) + unit.create(f, r, 5):set_skill("quarrying", 30) + f:set_origin(r) + return f +end + +local function dump_selection(sel) + local best = { score = 0, r = nil } + local r, score + for _, r in ipairs(sel) do + score = p.score(r) + if score > best.score then + best.r = r + best.score = score + end + print(score, r, r.terrain) + end + return best +end + +players = read_players() +local peasants = 20000 +local trees = 1000 +local turn = get_turn() +local sel +if #players > 0 then + eressea.read_game(("%d.dat"):format(turn)) + sel = p.select(regions(), peasants, trees) + if #sel > 0 then + local best = dump_selection(sel) + print("finest region, " .. best.score .. " points: " .. tostring(best.r)) + end +end +math.randomseed(os.time()) + +local newbs = {} +local per_region = 2 +local num_seeded = 2 +local start = nil +for _, p in ipairs(players) do + if num_seeded == per_region then + while not start or start.units() do + local index = math.random(#sel) + start = sel[index] + end + num_seeded = 0 + end + local dupe = false + for f in factions() do + if f.email==p.email then + print("seed: duplicate email " .. p.email .. " already used by faction " .. tostring(f)) + dupe = true + break + end + end + if not dupe then + num_seeded = num_seeded + 1 + f = seed(start, p.email, p.race or "human", p.lang or "de") + print("new faction ".. tostring(f) .. " starts in ".. tostring(start)) + table.insert(newbs, f) + end +end + +if #newbs > 0 then + init_reports() + for _, f in ipairs(newbs) do + write_report(f) + end + eressea.write_game(("%d.dat.new"):format(turn)) +end + diff --git a/scripts/populate.lua b/scripts/populate.lua new file mode 100644 index 000000000..fd01f2af1 --- /dev/null +++ b/scripts/populate.lua @@ -0,0 +1,31 @@ +local this = {} + +local function score(r, res) + assert(r) + res = res or "peasant" + local x, y, rn + local peas = r:get_resource(res) + for _, rn in pairs(r.adj) do + if rn and not rn.units() then + peas = peas + rn:get_resource(res) + end + end + return peas +end + +local function select(regions, peasants, trees) + local sel = {} + for r in regions do + if not r.plane and r.terrain~="ocean" and not r.units() then + if score(r, "peasant") >= peasants and score(r, "tree") >= trees then + table.insert(sel, r) + end + end + end + return sel +end + +return { + score = score, + select = select +} diff --git a/scripts/run-tests-e2.lua b/scripts/run-tests-e2.lua new file mode 100644 index 000000000..4a2b3e59e --- /dev/null +++ b/scripts/run-tests-e2.lua @@ -0,0 +1,22 @@ +-- Tests that work in all games. With game config of E2. +-- Tests are under scripts/test/e2 and all files must be in scripts/test/e2/init.lua + +path = 'scripts' +if config.install then + path = config.install .. '/' .. path + package.path = package.path .. ';' .. config.install .. '/lunit/?.lua' + --needed to find lunit if not run from eressea root. Needs right [lua] install setting in eressea.ini (point to eressea root from the start folder) +end +package.path = package.path .. ';' .. path .. '/?.lua;' .. path .. '/?/init.lua' + +config.rules = 'e2' + +require 'eressea' +require 'eressea.xmlconf' +require 'eressea.path' +require 'tests.e2' +require 'lunit' + +rules = require('eressea.' .. config.rules) +result = lunit.main() +return result.errors + result.failed diff --git a/scripts/run-tests-e3.lua b/scripts/run-tests-e3.lua index 3e5ecdcb2..47bcca60b 100644 --- a/scripts/run-tests-e3.lua +++ b/scripts/run-tests-e3.lua @@ -1,8 +1,11 @@ --- new tests 2014-06-11 +-- Tests that work in E3. With game config of E3. +-- Tests are under scripts/test/e3 and all files must be in scripts/test/e3/init.lua path = 'scripts' -if config.source_dir ~= nil then - path = config.source_dir .. '/' .. path +if config.install then + path = config.install .. '/' .. path + package.path = package.path .. ';' .. config.install .. '/lunit/?.lua' + --needed to find lunit if not run form eressea root. Needs right [lua] install setting in eressea.ini (point to eressea root from the start folder) end package.path = package.path .. ';' .. path .. '/?.lua;' .. path .. '/?/init.lua' @@ -16,4 +19,5 @@ require 'lunit' eressea.settings.set("rules.alliances", "0") rules = require('eressea.' .. config.rules) -lunit.main() +result = lunit.main() +return result.errors + result.failed diff --git a/scripts/run-tests.lua b/scripts/run-tests.lua index a230f8e97..d1306ddcd 100644 --- a/scripts/run-tests.lua +++ b/scripts/run-tests.lua @@ -1,8 +1,11 @@ --- new tests 2014-06-11 +-- Basic test without loading XML Config. Test care about needed settings. +-- Tests are under scripts/test/ and all files must be in scripts/test/init.lua path = 'scripts' -if config.source_dir ~= nil then - path = config.source_dir .. '/' .. path +if config.install then + path = config.install .. '/' .. path + package.path = package.path .. ';' .. config.install .. '/lunit/?.lua' + --needed to find lunit if not run form eressea root. Needs right [lua] install setting in eressea.ini (point to eressea root from the start folder) end package.path = package.path .. ';' .. path .. '/?.lua;' .. path .. '/?/init.lua' @@ -10,4 +13,5 @@ require 'eressea' require 'eressea.path' require 'tests' require 'lunit' -lunit.main() +result = lunit.main() +return result.errors + result.failed diff --git a/scripts/run-turn.lua b/scripts/run-turn.lua index 46095f216..60f2b6f63 100644 --- a/scripts/run-turn.lua +++ b/scripts/run-turn.lua @@ -26,18 +26,6 @@ function callbacks(rules, name, ...) end end -local function change_locales(localechange) - for loc, flist in pairs(localechange) do - for index, name in pairs(flist) do - f = get_faction(atoi36(name)) - if f ~= nil and f.locale ~= loc then - print("LOCALECHANGE ", f, f.locale, loc) - f.locale = loc - end - end - end -end - local function dbupdate() update_scores() dbname = config.dbname or 'eressea.db' @@ -127,64 +115,63 @@ local function write_scores() end function process(rules, orders) - local confirmed_multis = { } - local suspected_multis = { } + local confirmed_multis = { } + local suspected_multis = { } - if open_game(get_turn())~=0 then - eressea.log.error("could not read game") - return -1 - end - - callbacks(rules, 'init') - init_summary() + if open_game(get_turn())~=0 then + eressea.log.error("could not read game") + return -1 + end - -- run the turn: - if read_orders(orders) ~= 0 then - print("could not read " .. orders) - return -1 - end + callbacks(rules, 'init') + init_summary() - plan_monsters() + -- run the turn: + if read_orders(orders) ~= 0 then + print("could not read " .. orders) + return -1 + end - if nmr_check(config.maxnmrs or 80)~=0 then - return -1 - end + plan_monsters() - process_orders() - callbacks(rules, 'update') + if nmr_check(config.maxnmrs or 80)~=0 then + return -1 + end - local localechange = { de = { 'ii' } } - change_locales(localechange) + process_orders() + callbacks(rules, 'update') - write_files(config.locales) + write_files(config.locales) + dbupdate() - file = '' .. get_turn() .. '.dat' - if eressea.write_game(file)~=0 then - eressea.log.error("could not write game") - return -1 - end - return 0 + file = '' .. get_turn() .. '.dat' + if eressea.write_game(file)~=0 then + eressea.log.error("could not write game") + return -1 + end + return 0 end function run_turn(rules) - local turn = get_turn() - if turn<0 then - turn = read_turn() - set_turn(turn) - end + local turn = get_turn() + if turn<0 then + turn = read_turn() + set_turn(turn) + end - orderfile = orderfile or config.basepath .. '/orders.' .. turn - eressea.log.debug("executing turn " .. get_turn() .. " with " .. orderfile .. " with rules=" .. config.rules) - local result = process(rules, orderfile) - if result==0 then - dbupdate() - end - return result + orderfile = orderfile or config.basepath .. '/orders.' .. turn + eressea.log.debug("executing turn " .. get_turn() .. " with " .. orderfile .. " with rules=" .. config.rules) + local result = process(rules, orderfile) + return result end function file_exists(name) local f=io.open(name,"r") - if f~=nil then io.close(f) return true else return false end + if not f then + return false + end + io.close(f) + return true end if file_exists('execute.lock') then diff --git a/scripts/eressea/tests/bindings.lua b/scripts/tests/bindings.lua similarity index 100% rename from scripts/eressea/tests/bindings.lua rename to scripts/tests/bindings.lua diff --git a/scripts/eressea/tests/common.lua b/scripts/tests/common.lua similarity index 87% rename from scripts/eressea/tests/common.lua rename to scripts/tests/common.lua index 365b87195..fb1a29965 100644 --- a/scripts/eressea/tests/common.lua +++ b/scripts/tests/common.lua @@ -22,16 +22,16 @@ local function two_factions() return f1, f2 end -module("tests.eressea.common", package.seeall, lunit.testcase) +module("tests.common", package.seeall, lunit.testcase) function setup() eressea.free_game() - eressea.settings.set("nmr.removenewbie", "0") eressea.settings.set("nmr.timeout", "0") eressea.settings.set("NewbieImmunity", "0") eressea.settings.set("rules.economy.food", "4") eressea.settings.set("rules.encounters", "0") eressea.settings.set("rules.peasants.growth", "1") + eressea.settings.set("study.random_progress", "0") end function test_flags() @@ -39,7 +39,7 @@ function test_flags() local f = faction.create("flags@eressea.de", "halfling", "de") local u = unit.create(f, r, 1) local no = itoa36(f.id) - local flags = 587203585 + local flags = 50332673 f.flags = flags eressea.write_game("test.dat") @@ -511,140 +511,118 @@ function test_herbalism() end function test_mallorn() - local r = region.create(0, 0, "plain") - r:set_flag(1, false) -- not mallorn - r:set_resource("tree", 100) - assert(r:get_resource("tree")==100) - local m = region.create(0, 0, "plain") - m:set_flag(1, true) -- mallorn - m:set_resource("tree", 100) - assert(m:get_resource("tree")==100) - - local f = faction.create("noreply13@eressea.de", "human", "de") + local r = region.create(0, 0, "plain") + r:set_flag(1, false) -- not mallorn + r:set_resource("tree", 100) + assert(r:get_resource("tree")==100) + local m = region.create(0, 0, "plain") + m:set_flag(1, true) -- mallorn + m:set_resource("tree", 100) + assert(m:get_resource("tree")==100) - local u1 = unit.create(f, r, 1) - u1:add_item("money", u1.number * 100) - u1:set_skill("forestry", 2) - u1:clear_orders() - u1:add_order("MACHE HOLZ") + local f = faction.create("noreply13@eressea.de", "human", "de") - local u2 = unit.create(f, m, 1) - u2:add_item("money", u2.number * 100) - u2:set_skill("forestry", 2) - u2:clear_orders() - u2:add_order("MACHE HOLZ") + local u1 = unit.create(f, r, 1) + u1:add_item("money", u1.number * 100) + u1:set_skill("forestry", 2) + u1:clear_orders() + u1:add_order("MACHE HOLZ") - local u3 = unit.create(f, m, 1) - u3:add_item("money", u3.number * 100) - u3:set_skill("forestry", 2) - u3:clear_orders() - u3:add_order("MACHE Mallorn") - - process_orders() - - assert_equal(2, u1:get_item("log")) - assert_equal(2, u2:get_item("log")) - local mallorn_cfg = config.get_resource("mallorn") - if mallorn_cfg then - assert_equal(1, u3:get_item("mallorn")) - else - assert_equal(-1, u3:get_item("mallorn")) - assert_equal(0, u3:get_item("log")) - end + local u2 = unit.create(f, m, 1) + u2:add_item("money", u2.number * 100) + u2:set_skill("forestry", 2) + u2:clear_orders() + u2:add_order("MACHE HOLZ") + + local u3 = unit.create(f, m, 1) + u3:add_item("money", u3.number * 100) + u3:set_skill("forestry", 2) + u3:clear_orders() + u3:add_order("MACHE Mallorn") + + process_orders() + + assert_equal(2, u1:get_item("log")) + assert_equal(2, u2:get_item("log")) + local mallorn_cfg = config.get_resource("mallorn") + if mallorn_cfg then + assert_equal(1, u3:get_item("mallorn")) + else + assert_equal(-1, u3:get_item("mallorn")) + assert_equal(0, u3:get_item("log")) + end end function test_coordinate_translation() - local pl = plane.create(1, 500, 500, 1001, 1001) -- astralraum - local pe = plane.create(1, -8761, 3620, 23, 23) -- eternath - local r = region.create(1000, 1000, "plain") - local f = faction.create("noreply14@eressea.de", "human", "de") - assert_not_equal(nil, r) - assert_equal(r.x, 1000) - assert_equal(r.y, 1000) - local nx, ny = plane.normalize(pl, r.x, r.y) - assert_equal(nx, 1000) - assert_equal(ny, 1000) - local r1 = region.create(500, 500, "plain") - f:set_origin(r1) - nx, ny = f:normalize(r1) - assert_equal(0, nx) - assert_equal(0, ny) - local r0 = region.create(0, 0, "plain") - nx, ny = f:normalize(r0) - assert_equal(0, nx) - assert_equal(0, ny) - nx, ny = f:normalize(r) - assert_equal(500, nx) - assert_equal(500, ny) - local rn = region.create(1010, 1010, "plain") - nx, ny = f:normalize(rn) - assert_equal(-491, nx) - assert_equal(-491, ny) + local pl = plane.create(1, 500, 500, 1001, 1001) -- astralraum + local pe = plane.create(1, -8761, 3620, 23, 23) -- eternath + local r = region.create(1000, 1000, "plain") + local f = faction.create("noreply14@eressea.de", "human", "de") + assert_not_equal(nil, r) + assert_equal(r.x, 1000) + assert_equal(r.y, 1000) + local nx, ny = plane.normalize(pl, r.x, r.y) + assert_equal(nx, 1000) + assert_equal(ny, 1000) + local r1 = region.create(500, 500, "plain") + f:set_origin(r1) + nx, ny = f:normalize(r1) + assert_equal(0, nx) + assert_equal(0, ny) + local r0 = region.create(0, 0, "plain") + nx, ny = f:normalize(r0) + assert_equal(0, nx) + assert_equal(0, ny) + nx, ny = f:normalize(r) + assert_equal(500, nx) + assert_equal(500, ny) + local rn = region.create(1010, 1010, "plain") + nx, ny = f:normalize(rn) + assert_equal(-491, nx) + assert_equal(-491, ny) - local re = region.create(-8760, 3541, "plain") -- eternath - nx, ny = f:normalize(rn) - assert_equal(-491, nx) - assert_equal(-491, ny) + local re = region.create(-8760, 3541, "plain") -- eternath + nx, ny = f:normalize(rn) + assert_equal(-491, nx) + assert_equal(-491, ny) end function test_control() - local u1, u2 = two_units(region.create(0, 0, "plain"), two_factions()) - local r = u1.region - local b = building.create(r, "castle") - u1.building = b - u2.building = b - assert_equal(u1, b.owner) - u1:clear_orders() - u1:add_order("GIB " .. itoa36(u2.id) .. " KOMMANDO") - u1:add_order("VERLASSE") - process_orders() - assert_equal(u2, b.owner) -end - -function test_store_unit() - local r = region.create(0, 0, "plain") - local f = faction.create("noreply15@eressea.de", "human", "de") - local u = unit.create(f, r, 1) - local fid = f.id - u:add_item("money", u.number * 100) - local filename = config.basepath .. "/data/test.dat" - store = storage.create(filename, "wb") - assert_not_equal(store, nil) - store:write_unit(u) - store:close() - eressea.free_game() - -- recreate world: - r = region.create(0, 0, "plain") - f = faction.create("noreply16@eressea.de", "human", "de") - f.id = fid - store = storage.create(filename, "rb") - assert_not_nil(store) - u = store:read_unit() - store:close() - assert(u) - assert(u:get_item("money") == u.number * 100) + local u1, u2 = two_units(region.create(0, 0, "plain"), two_factions()) + local r = u1.region + local b = building.create(r, "castle") + u1.building = b + u2.building = b + assert_equal(u1, b.owner) + u1:clear_orders() + u1:add_order("GIB " .. itoa36(u2.id) .. " KOMMANDO") + u1:add_order("VERLASSE") + process_orders() + assert_equal(u2, b.owner) end function test_building_other() - local r = region.create(0,0, "plain") - local f1 = faction.create("noreply17@eressea.de", "human", "de") - local f2 = faction.create("noreply18@eressea.de", "human", "de") - local b = building.create(r, "castle") - b.size = 10 - local u1 = unit.create(f1, r, 3) - u1.building = b - u1:add_item("money", 100) + local r = region.create(0,0, "plain") + local f1 = faction.create("noreply17@eressea.de", "human", "de") + local f2 = faction.create("noreply18@eressea.de", "human", "de") + local b = building.create(r, "castle") + b.size = 10 + local u1 = unit.create(f1, r, 3) + u1.building = b + u1:add_item("money", 100) - local u2 = unit.create(f2, r, 3) - u2:set_skill("building", 10) - u2:add_item("money", 100) - u2:add_item("stone", 100) - u2:clear_orders() - u2:add_order("MACHEN BURG " .. itoa36(b.id)) - process_orders() - assert_not_equal(10, b.size) + local u2 = unit.create(f2, r, 3) + u2:set_skill("building", 10) + u2:add_item("money", 100) + u2:add_item("stone", 100) + u2:clear_orders() + u2:add_order("MACHEN BURG " .. itoa36(b.id)) + process_orders() + assert_not_equal(10, b.size) end +-- segfault above + function test_config() assert_not_equal(nil, config.basepath) assert_not_equal(nil, config.locales) @@ -790,6 +768,7 @@ function test_expensive_skills_cost_money() u:add_item("money", 10000) u:clear_orders() u:add_order("LERNEN MAGIE Gwyrrd") + assert_equal(0, u:get_skill("magic")) process_orders() assert_equal(9900, u:get_item("money")) assert_equal(1, u:get_skill("magic")) @@ -981,7 +960,6 @@ module("tests.report", package.seeall, lunit.testcase) function setup() eressea.free_game() - eressea.settings.set("nmr.removenewbie", "0") eressea.settings.set("nmr.timeout", "0") eressea.settings.set("rules.economy.food", "4") end @@ -995,7 +973,6 @@ local function find_in_report(f, pattern, extension) report:close() local start, _ = string.find(t, pattern) --- posix.unlink(filename) return start~=nil end @@ -1052,6 +1029,7 @@ function test_coordinates_noname_plane() end function test_lighthouse() + eressea.free_game() local r = region.create(0, 0, "mountain") local f = faction.create("noreply@eressea.de", "human", "de") region.create(1, 0, "mountain") @@ -1092,7 +1070,7 @@ function test_parser() local r = region.create(0, 0, "mountain") local f = faction.create("noreply@eressea.de", "human", "de") local u = unit.create(f, r, 1) - local filename = config.basepath .. "/data/orders.txt" + local filename = "orders.txt" local file = io.open(filename, "w") assert_not_nil(file) diff --git a/scripts/tests/config.lua b/scripts/tests/config.lua index b24da72bc..d21ecda1e 100644 --- a/scripts/tests/config.lua +++ b/scripts/tests/config.lua @@ -36,4 +36,3 @@ function test_read_ship() s = ship.create(nil, "boat") assert_not_nil(s) end - diff --git a/scripts/tests/e2/destroy.lua b/scripts/tests/e2/destroy.lua new file mode 100644 index 000000000..a4e84330d --- /dev/null +++ b/scripts/tests/e2/destroy.lua @@ -0,0 +1,49 @@ +require "lunit" + +module("tests.e2.destroy", package.seeall, lunit.testcase) + +function setup() + eressea.free_game() + eressea.settings.set("NewbieImmunity", "0") +end + +function test_dont_move_after_destroy() + local r1 = region.create(0, 0, "plain") + local r2 = region.create(1, 0, "plain") + local f = faction.create("test@example.com", "human", "de") + local u = unit.create(f, r1, 1) + u.building = building.create(u.region, "castle") + u:clear_orders() + u:add_order("NACH O") + u:add_order("ZERSTOERE " .. itoa36(u.building.id)) + process_orders() + if not u.region then + print("shit happened ", u.number) + end + assert_equal(r1, u.region) + assert_equal(nil, u.building) +end + +function test_dont_destroy_after_attack() + local r1 = region.create(0, 0, "plain") + local u = unit.create(faction.create("one@example.com", "human", "de"), r1, 10) + local u2 = unit.create(faction.create("two@example.com", "human", "de"), r1, 1) + u.building = building.create(u.region, "castle") + u:clear_orders() + u:add_order("ATTACKIERE " .. itoa36(u2.id)) + u:add_order("ZERSTOERE " .. itoa36(u.building.id)) + process_orders() + assert_not_nil(u.building) +end + +function test_destroy_is_long() + local r1 = region.create(0, 0, "plain") + local u = unit.create(faction.create("one@example.com", "human", "de"), r1, 10) + u.building = building.create(u.region, "castle") + u:clear_orders() + u:add_order("LERNE Unterhaltung") + u:add_order("ZERSTOERE " .. itoa36(u.building.id)) + process_orders() + assert_equal(0, u:get_skill("entertainment")) + assert_equal(nil, u.building) +end diff --git a/scripts/eressea/tests/eressea.lua b/scripts/tests/e2/e2features.lua similarity index 90% rename from scripts/eressea/tests/eressea.lua rename to scripts/tests/e2/e2features.lua index 789b81b6b..8e57983e2 100644 --- a/scripts/eressea/tests/eressea.lua +++ b/scripts/tests/e2/e2features.lua @@ -1,6 +1,6 @@ require "lunit" -module("tests.e3.e2features", package.seeall, lunit.testcase ) +module("tests.e2.e2features", package.seeall, lunit.testcase ) local function one_unit(r, f) local u = unit.create(f, r, 1) @@ -23,6 +23,7 @@ function setup() eressea.free_game() eressea.settings.set("nmr.timeout", "0") eressea.settings.set("rules.economy.food", "4") + eressea.settings.set("rules.ship.storms", "0") end function test_learn() @@ -107,7 +108,7 @@ function test_ship_capacity() local r = region.create(0,0, "ocean") region.create(1,0, "ocean") local r2 = region.create(2,0, "ocean") - local f = faction.create("noreply@eressea.de", "human", "de") + local f = faction.create("capacity@eressea.de", "human", "de") -- u1 is at the limit and moves local s1 = ship.create(r, "boat") @@ -269,7 +270,7 @@ end function test_block_movement_aots() eressea.settings.set("rules.guard.base_stop_prob", "0.0") eressea.settings.set("rules.guard.skill_stop_prob", "1.0") - eressea.settings.set("rules.guard.amulet_stop_prob", "1.1") + eressea.settings.set("rules.guard.amulet_stop_prob", "1.0") local r0 = region.create(0, 0, "plain") local r1 = region.create(1, 0, "plain") @@ -298,7 +299,7 @@ function test_block_movement_aots() u:add_order("NACH o o") end - u12:add_item("aots", 10) + u12:add_item("aots", 1) u22:set_skill("stealth", 1) process_orders() @@ -334,27 +335,3 @@ function test_stonegolems() assert_equal(1 ,u2.number, "There shoud be one Stone Golems") -- end test Stone Golems four stones end - -function test_only_building_owner_can_set_not_paid() - local r = region.create(0, 0, "plain") - local f = faction.create("noreply@eressea.de", "human", "de") - local u1 = unit.create(f, r, 1) - local u2 = unit.create(f, r, 1) - local mine = building.create(r, "mine") - mine.size = 2 - u1:add_item("money", 500) - u1.building = mine - u2.building = mine - u1:clear_orders() - u2:clear_orders() --- Test that Bezahle nicht is working - u1:add_order("Bezahle nicht") - process_orders() - assert_equal(500, u1:get_item("money")) - u1:clear_orders() --- Test that bug fix 0001976 is working --- Bezahle nicht is not working - u2:add_order("Bezahle nicht") - process_orders() - assert_equal(0, u1:get_item("money")) -end diff --git a/scripts/tests/e2/guard.lua b/scripts/tests/e2/guard.lua new file mode 100644 index 000000000..b1c9d9c4f --- /dev/null +++ b/scripts/tests/e2/guard.lua @@ -0,0 +1,77 @@ +require "lunit" + +module("tests.e2.guard", package.seeall, lunit.testcase) + +function setup() + eressea.free_game() + eressea.settings.set("nmr.timeout", "0") + eressea.settings.set("NewbieImmunity", "0") + eressea.settings.set("rules.economy.food", "4") +end + +function test_guard_unarmed() + local r1 = region.create(0, 0, "plain") + local f1 = faction.create("hodor@eressea.de", "human", "de") + local u1 = unit.create(f1, r1, 1) + assert_equal(nil, u1.guard) + u1:clear_orders() + u1:add_order("BEWACHE") + process_orders() + assert_equal(nil, u1.guard) +end + +function test_guard_armed() + local r1 = region.create(0, 0, "plain") + local f1 = faction.create("hodor@eressea.de", "human", "de") + local u1 = unit.create(f1, r1, 1) + assert_equal(nil, u1.guard) + u1:add_item("sword", 1) + u1:set_skill("melee", 2) + u1:clear_orders() + u1:add_order("BEWACHE") + process_orders() + assert_equal(249, u1.guard) +end + +function test_guard_allows_move_after_combat() -- bug 1493 + local r1 = region.create(0, 0, "plain") + local r2 = region.create(1, 0, "plain") + local f1 = faction.create("bernd@eressea.de", "human", "de") + local u1 = unit.create(f1, r1, 10) + local uid1 = u1.id + local f2 = faction.create("horst@eressea.de", "human", "de") + local u2 = unit.create(f2, r1, 1) + u1:add_order("BEWACHE") + u1:add_item("sword", 10) + u1:set_skill("melee", 2) + u1:clear_orders() + u1:add_order("BEWACHE") + process_orders() + assert_equal(249, u1.guard) + u1:clear_orders() + u1:add_order("NACH O") + u1:add_order("ATTACKIERE " .. itoa36(u2.id)) + process_orders() + u1 = get_unit(uid1) + assert_equal(r2, u1.region) +end + +function test_no_guard_no_move_after_combat() -- bug 1493 + local r1 = region.create(0, 0, "plain") + local r2 = region.create(1, 0, "plain") + local f1 = faction.create("bernd@eressea.de", "human", "de") + local u1 = unit.create(f1, r1, 10) + local uid1 = u1.id + local f2 = faction.create("horst@eressea.de", "human", "de") + local u2 = unit.create(f2, r1, 1) + u1:add_order("BEWACHE") + u1:add_item("sword", 10) + u1:set_skill("melee", 2) + assert_equal(nil, u1.guard) + u1:clear_orders() + u1:add_order("NACH O") + u1:add_order("ATTACKIERE " .. itoa36(u2.id)) + process_orders() + u1 = get_unit(uid1) + assert_equal(r1, u1.region) +end diff --git a/scripts/tests/e2/init.lua b/scripts/tests/e2/init.lua new file mode 100644 index 000000000..32199b257 --- /dev/null +++ b/scripts/tests/e2/init.lua @@ -0,0 +1,11 @@ +require 'tests.e2.undead' +require 'tests.e2.shiplanding' +require 'tests.e2.e2features' +require 'tests.e2.movement' +require 'tests.e2.destroy' +require 'tests.e2.guard' +require 'tests.e2.stealth' +require 'tests.orders' +require 'tests.common' +require 'tests.storage' +require 'tests.magicbag' diff --git a/scripts/tests/e2/movement.lua b/scripts/tests/e2/movement.lua new file mode 100644 index 000000000..7e20e41ca --- /dev/null +++ b/scripts/tests/e2/movement.lua @@ -0,0 +1,85 @@ +require "lunit" + +module("tests.e2.movement", package.seeall, lunit.testcase) + +function setup() + eressea.free_game() + eressea.settings.set("nmr.timeout", "0") + eressea.settings.set("NewbieImmunity", "0") +end + +function test_dolphin_on_land() + local r1 = region.create(0, 0, "plain") + local r2 = region.create(1, 0, "plain") + local f = faction.create("noreply@eressea.de", "human", "de") + local u1 = unit.create(f, r1, 1) + u1.race = "dolphin" + u1:clear_orders() + u1:add_order("NACH O") + process_orders() + assert_equal(r1, u1.region) +end + +function test_dolphin_to_land() + local r1 = region.create(0, 0, "ocean") + local r2 = region.create(1, 0, "plain") + local f = faction.create("noreply@eressea.de", "human", "de") + local u1 = unit.create(f, r1, 1) + u1.race = "dolphin" + u1:clear_orders() + u1:add_order("NACH O") + process_orders() + assert_equal(r2, u1.region) +end + +function test_dolphin_in_ocean() + local r1 = region.create(0, 0, "ocean") + local r2 = region.create(1, 0, "ocean") + local f = faction.create("noreply@eressea.de", "human", "de") + local u1 = unit.create(f, r1, 1) + u1.race = "dolphin" + u1:clear_orders() + u1:add_order("NACH O") + process_orders() + assert_equal(r2, u1.region) +end + +function test_follow() + local r1 = region.create(0, 0, "plain") + local r2 = region.create(1, 0, "plain") + local f = faction.create("test@example.com", "human", "de") + local u1 = unit.create(f, r1, 1) + local u2 = unit.create(f, r1, 1) + u1:clear_orders() + u2:clear_orders() + u1:add_item("money", 100) + u2:add_item("money", 100) + u1:add_order("NACH O") + u2:add_order("FOLGE EINHEIT " .. itoa36(u1.id)) + process_orders() + assert_equal(u1.region, r2) + assert_equal(u2.region, r2) +end + +function test_follow_ship() + local r1 = region.create(0, 0, "plain") + region.create(1, 0, "ocean") + region.create(2, 0, "ocean") + local f = faction.create("test@example.com", "human", "de") + local u1 = unit.create(f, r1, 1) + local u2 = unit.create(f, r1, 1) + u1:add_item("money", 100) + u2:add_item("money", 100) + u1.ship = ship.create(r1, "boat") + assert(u1.ship) + u1:set_skill("sailing", 2) + u1:clear_orders() + u1:add_order("NACH O O") + u2.ship = ship.create(r1, "boat") + u2:set_skill("sailing", 2) + u2:clear_orders() + u2:add_order("FOLGE SCHIFF " .. itoa36(u1.ship.id)) + process_orders() + assert_equal(2, u1.region.x) + assert_equal(2, u2.region.x) +end diff --git a/scripts/tests/rules.lua b/scripts/tests/e2/shiplanding.lua similarity index 74% rename from scripts/tests/rules.lua rename to scripts/tests/e2/shiplanding.lua index 6ed6601cb..a46a7da37 100644 --- a/scripts/tests/rules.lua +++ b/scripts/tests/e2/shiplanding.lua @@ -1,19 +1,17 @@ require "lunit" -module("tests.rules", package.seeall, lunit.testcase) +module("tests.e2.shiplanding", package.seeall, lunit.testcase) function setup() eressea.free_game() - eressea.settings.set("nmr.removenewbie", "0") eressea.settings.set("nmr.timeout", "0") eressea.settings.set("NewbieImmunity", "0") - eressea.config.parse('{ "races": { "human" : {}}}') end function test_landing1() local ocean = region.create(1, 0, "ocean") local r = region.create(0, 0, "plain") - local f = faction.create("noreply@eressea.de", "insects", "de") + local f = faction.create("noreply@eressea.de", "human", "de") local f2 = faction.create("noreply@eressea.de", "human", "de") local s = ship.create(ocean, "longboat") local u1 = unit.create(f, ocean, 1) @@ -31,7 +29,33 @@ function test_landing1() assert_equal(r.id, u1.region.id) -- the plain case: okay end -function test_landing_harbour() +function test_landing_harbour_with_help() + local ocean = region.create(1, 0, "ocean") + local r = region.create(0, 0, "glacier") + local harbour = building.create(r, "harbour") + harbour.size = 25 + local f = faction.create("noreply@eressea.de", "human", "de") + local f2 = faction.create("noreply@eressea.de", "human", "de") + local s = ship.create(ocean, "longboat") + local u1 = unit.create(f, ocean, 1) + local u2 = unit.create(f2, r, 1) + assert_not_nil(u2) + u1:add_item("money", 1000) + u2:add_item("money", 1000) + u2.building = harbour + u2:clear_orders() + u2:add_order("KONTAKTIERE " .. itoa36(u1.id)) + + u1.ship = s + u1:set_skill("sailing", 10) + u1:clear_orders() + u1:add_order("NACH w") + process_orders() + + assert_equal(r.id, u1.region.id) -- glacier with harbour and help-- okay +end + +function test_landing_harbour_without_help() local ocean = region.create(1, 0, "ocean") local r = region.create(0, 0, "glacier") local harbour = building.create(r, "harbour") @@ -52,7 +76,7 @@ function test_landing_harbour() u1:add_order("NACH w") process_orders() - assert_equal(r.id, u1.region.id) -- glacier with harbour -- okay + assert_equal(ocean.id, u1.region.id) -- glacier with harbour and no help-- cannot land end function test_landing_harbour_unpaid() @@ -61,13 +85,12 @@ function test_landing_harbour_unpaid() local harbour = building.create(r, "harbour") harbour.size = 25 local f = faction.create("noreply@eressea.de", "human", "de") - local f2 = faction.create("noreply@eressea.de", "human", "de") local s = ship.create(ocean, "longboat") local u1 = unit.create(f, ocean, 1) - local u2 = unit.create(f2, r, 1) + local u2 = unit.create(f, r, 1) assert_not_nil(u2) u1:add_item("money", 1000) - u2:add_item("money", 1000) + u2:add_item("money", 20) u1.ship = s u1:set_skill("sailing", 10) @@ -91,8 +114,7 @@ function test_landing_terrain() u2:add_item("money", 1000) u1.ship = s - u1:set_skill("sailing", 10) - u1:clear_orders() + u1:set_skill("sailing", 10) u1:clear_orders() u1:add_order("NACH w") process_orders() @@ -104,7 +126,7 @@ function test_landing_insects() local r = region.create(0, 0, "glacier") local harbour = building.create(r, "harbour") harbour.size = 25 - local f = faction.create("noreply@eressea.de", "insects", "de") + local f = faction.create("noreply@eressea.de", "insect", "de") local f2 = faction.create("noreply@eressea.de", "human", "de") local s = ship.create(ocean, "longboat") local u1 = unit.create(f, ocean, 1) diff --git a/scripts/eressea/tests/stealth.lua b/scripts/tests/e2/stealth.lua similarity index 94% rename from scripts/eressea/tests/stealth.lua rename to scripts/tests/e2/stealth.lua index 6d1a1dee4..aa0341c00 100644 --- a/scripts/eressea/tests/stealth.lua +++ b/scripts/tests/e2/stealth.lua @@ -1,11 +1,11 @@ require "lunit" -module('eressea.tests.stealth', package.seeall, lunit.testcase) +module('tests.e2.stealth', package.seeall, lunit.testcase) local f local u -local settings +local settings = {} local function set_rule(key, value) if value==nil then diff --git a/scripts/tests/e2/undead.lua b/scripts/tests/e2/undead.lua new file mode 100644 index 000000000..9f3f67f13 --- /dev/null +++ b/scripts/tests/e2/undead.lua @@ -0,0 +1,31 @@ +require "lunit" + +module("tests.e2.undead", package.seeall, lunit.testcase) + +function setup() + eressea.free_game() +end + +function test_undead_give_item() + local r1 = region.create(0, 0, "plain") + local f1 = faction.create("hodor@eressea.de", "human", "de") + local u1 = unit.create(f1, r1, 1) + u1.race = "undead" + u1:clear_orders() + u1:add_item("log", 1) + u1:add_order("GIB 0 1 Holz") + process_orders() + assert_equal(0, u1:get_item("log")) +end + +function test_undead_dont_give_person() + local r1 = region.create(0, 0, "plain") + local f1 = faction.create("hodor@eressea.de", "human", "de") + local u1 = unit.create(f1, r1, 2) + u1.race = "undead" + u1:clear_orders() + u1:add_item("log", 1) + u1:add_order("GIB 0 1 Person") + process_orders() + assert_equal(2, u1.number) +end diff --git a/scripts/tests/e3/castles.lua b/scripts/tests/e3/castles.lua index 1aa2bb17c..b9cbabe0b 100644 --- a/scripts/tests/e3/castles.lua +++ b/scripts/tests/e3/castles.lua @@ -25,3 +25,28 @@ function test_small_castles() assert_equal("site", b:get_typename(9)) assert_equal("fortification", b:get_typename(10)) end + +function test_build_normal() + local r = region.create(0, 0, "plain") + local f = faction.create("noreply@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + u:clear_orders() + u:add_item("stone", 10) + u:set_skill("building", 10) + u:add_order("MACHE BURG") + process_orders() + assert_not_nil(u.building) + assert_equal(10, u.building.size) +end + +function test_build_packice() + local r = region.create(0, 0, "packice") + local f = faction.create("noreply@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + u:clear_orders() + u:add_item("stone", 10) + u:set_skill("building", 10) + u:add_order("MACHE BURG") + process_orders() + assert_equal(nil, u.building) +end diff --git a/scripts/tests/e3/init.lua b/scripts/tests/e3/init.lua index fe7d0c223..2a31be599 100644 --- a/scripts/tests/e3/init.lua +++ b/scripts/tests/e3/init.lua @@ -3,3 +3,7 @@ require 'tests.e3.stealth' require 'tests.e3.spells' require 'tests.e3.rules' require 'tests.e3.parser' +require 'tests.e3.morale' +require 'tests.orders' +require 'tests.common' +require 'tests.magicbag' diff --git a/scripts/tests/morale.lua b/scripts/tests/e3/morale.lua similarity index 99% rename from scripts/tests/morale.lua rename to scripts/tests/e3/morale.lua index ddbdb9526..a47b0e9e4 100644 --- a/scripts/tests/morale.lua +++ b/scripts/tests/e3/morale.lua @@ -3,7 +3,7 @@ require "lunit" module("tests.e3.morale", package.seeall, lunit.testcase ) function setup() - eressea.free_game() + eressea.game.reset() end function test_when_owner_returns_morale_drops_only_2() diff --git a/scripts/tests/e3/rules.lua b/scripts/tests/e3/rules.lua index 193551ea9..902a91741 100644 --- a/scripts/tests/e3/rules.lua +++ b/scripts/tests/e3/rules.lua @@ -76,9 +76,7 @@ function disable_test_market_action() b.size = 10 u.building = b update_owners() - for r in regions() do - market_action(r) - end + process.markets() assert_equal(35, u:get_item("balm")) assert_equal(70, u:get_item("h2")) end @@ -148,25 +146,6 @@ function test_no_stealth() assert_equal(-1, u:get_skill("stealth")) end ---[[ -function test_analyze_magic() - local r1 = region.create(0,0, "plain") - local r2 = region.create(1,0, "plain") - local f = faction.create("noreply@eressea.de", "human", "de") - - local u = unit.create(f, r2, 1) - - u.race = "elf" - u:set_skill("magic", 6) - u.magic = "gwyrrd" - u.aura = 60 - u:add_spell("analyze_magic") - u:clear_orders() - u:add_order("Zaubere stufe 2 'Magie analysieren' REGION 1,0") - process_orders() -end -]]-- - function test_seecast() local r = region.create(0,0, "plain") for i = 1,10 do @@ -481,7 +460,6 @@ function test_canoe_passes_through_land() u1:add_order("NACH O O O") process_orders() assert_equal(land, u2.region, "canoe did not stop at coast") - u1:add_order("NACH O O O") process_orders() assert_equal(dst, sh.region, "canoe could not leave coast") assert_equal(dst, u1.region, "canoe could not leave coast") @@ -712,7 +690,7 @@ function test_golem_use_four_iron() assert_equal(4, u1:get_item("towershield")) end -function skip_test_silver_weight_stops_movement() +function test_silver_weight_stops_movement() local r1 = region.create(1, 1, "plain") local r2 = region.create(2, 1, "plain") region.create(3, 1, "plain") @@ -729,7 +707,7 @@ function skip_test_silver_weight_stops_movement() assert_equal(r2, u1.region) end -function skip_test_silver_weight_stops_ship() +function test_silver_weight_stops_ship() local r1 = region.create(1, 1, "ocean") local r2 = region.create(2, 1, "ocean") region.create(3, 1, "ocean") @@ -771,11 +749,49 @@ function test_building_owner_can_enter_ship() assert_equal(null, u1.building, "owner of the building can not go into a ship") end -function test_weightless_silver() +function test_only_building_owner_can_set_not_paid() + local r = region.create(0, 0, "plain") + local f = faction.create("noreply@eressea.de", "human", "de") + local u1 = unit.create(f, r, 1) + local u2 = unit.create(f, r, 1) + local mine = building.create(r, "mine") + mine.size = 2 + u1:add_item("money", 500) + u1.building = mine + u2.building = mine + u1:clear_orders() + u2:clear_orders() +-- Test that Bezahle nicht is working + u1:add_order("Bezahle nicht") + process_orders() + assert_equal(500, u1:get_item("money")) + u1:clear_orders() +-- Test that bug fix 0001976 is working +-- Bezahle nicht is not working + u2:add_order("Bezahle nicht") + process_orders() + assert_equal(0, u1:get_item("money")) +end + +function test_spyreport_message() local r1 = region.create(1, 2, "plain") local f1 = faction.create("noreply@eressea.de", "human", "de") local u1 = unit.create(f1, r1, 1) - assert_equal(1000, u1.weight) - u1:add_item("money", 540) - assert_equal(1000, u1.weight) + local u2 = unit.create(f1, r1, 1) + msg = message.create("spyreport") + msg:set_unit("spy", u1) + msg:set_unit("target", u2) + msg:set_string("status", "hodor") + assert_not_equal("", msg:render("de")) + assert_not_equal("", msg:render("en")) +end + +function test_volcanooutbreak_message() + local r1 = region.create(1, 0, "plain") + local r2 = region.create(1, 1, "plain") + msg = message.create("volcanooutbreak") + msg:set_region("regionn", r1) + msg:set_region("regionv", r2) + assert_not_equal("", msg:render("de")) + assert_not_equal("", msg:render("en")) end diff --git a/scripts/tests/spells-e2.lua b/scripts/tests/e3/spells-e2.lua similarity index 100% rename from scripts/tests/spells-e2.lua rename to scripts/tests/e3/spells-e2.lua diff --git a/scripts/tests/e3/spells.lua b/scripts/tests/e3/spells.lua index 21a743646..f99e4687b 100644 --- a/scripts/tests/e3/spells.lua +++ b/scripts/tests/e3/spells.lua @@ -5,7 +5,6 @@ module("tests.e3.spells", package.seeall, lunit.testcase) function setup() eressea.game.reset() eressea.settings.set("magic.fumble.enable", "0") - eressea.settings.set("nmr.removenewbie", "0") eressea.settings.set("nmr.timeout", "0") eressea.settings.set("rules.peasants.growth", "0") end @@ -44,3 +43,24 @@ function test_blessedharvest_lasts_n_turn() process_orders() assert_equal(900, r:get_resource("money")) end + +function test_magic() + local r = region.create(0, 0, "plain") + local f = faction.create("noreply@eressea.de", "halfling", "de") + local u = unit.create(f, r) + local b = building.create(r, "castle") + + u.race = "dwarf" + u.magic = "gwyrrd" + u:set_skill("magic", 30) + u.aura = 300 + + u:add_spell("protective_runes") + u:add_spell("analyze_magic") + u:clear_orders() + u.building = b + u:add_order("ZAUBERE \"Magie analysieren\" BURG " .. itoa36(b.id)); + process_orders() +-- there used to be a SEGFAULT when writing reports here: +-- write_reports() +end diff --git a/scripts/tests/eressea.lua b/scripts/tests/eressea.lua deleted file mode 100644 index 789b81b6b..000000000 --- a/scripts/tests/eressea.lua +++ /dev/null @@ -1,360 +0,0 @@ -require "lunit" - -module("tests.e3.e2features", package.seeall, lunit.testcase ) - -local function one_unit(r, f) - local u = unit.create(f, r, 1) - u:add_item("money", u.number * 100) - u:clear_orders() - return u -end - -local function two_factions() - local f1 = faction.create("one@eressea.de", "human", "de") - local f2 = faction.create("two@eressea.de", "human", "de") - return f1, f2 -end - -local function two_units(r, f1, f2) - return one_unit(r, f1), one_unit(r, f2) -end - -function setup() - eressea.free_game() - eressea.settings.set("nmr.timeout", "0") - eressea.settings.set("rules.economy.food", "4") -end - -function test_learn() - eressea.settings.set("study.random_progress", "0") - local r = region.create(0, 0, "plain") - local f = faction.create("noreply@eressea.de", "human", "de") - f.age = 20 - local u = unit.create(f, r) - u:clear_orders() - u:add_order("@LERNEN Reiten") - process_orders() - assert_equal(1, u:get_skill("riding")) - process_orders() - process_orders() - assert_equal(2, u:get_skill("riding")) - process_orders() - process_orders() - process_orders() - assert_equal(3, u:get_skill("riding")) -end - -function test_teach() - eressea.settings.set("study.random_progress", "0") - local r = region.create(0, 0, "plain") - local f = faction.create("noreply@eressea.de", "human", "de") - f.age = 20 - local u = unit.create(f, r, 10) - local u2 = unit.create(f, r) - u:clear_orders() - u:add_order("@LERNEN reiten") - u2:clear_orders() - u2:add_order("LEHREN " .. itoa36(u.id)) - u2:set_skill("riding", 4) - process_orders() - assert_equal(1, u:get_skill("riding")) - process_orders() - assert_equal(2, u:get_skill("riding")) -end - -function test_rename() - local r = region.create(0, 0, "plain") - local f = faction.create("noreply@eressea.de", "human", "de") - local u = unit.create(f, r) - u:add_item("aoh", 1) - assert_equal(u:get_item("ao_healing"), 1) -end - -function DISABLE_test_alp() - local r = region.create(0,0, "plain") - local f = faction.create("noreply@eressea.de", "human", "de") - local u = unit.create(f, r, 1) - local u2 = unit.create(f, r, 1) - u.race = "elf" - u:set_skill("magic", 10) - u:add_item("money", 3010) - u.magic = "illaun" - u.aura = 200 - u.ship = s1 - u:add_spell("summon_alp") - u:clear_orders() - u:add_order("ZAUBERE 'Alp' " .. itoa36(u2.id)) - process_orders() - print(get_turn(), f) - write_reports() -end - -function test_unit_limit_is_1500() - local r = region.create(0,0, "plain") - local f = faction.create("noreply@eressea.de", "human", "de") - for i = 1,1500 do - unit.create(f, r, 1) - end - local u = unit.create(f, r, 0) - u:add_item("money", 20000) - u:clear_orders() - u:add_order("REKRUTIEREN 1") - process_orders() - assert_equal(1, u.number) -end - -function test_ship_capacity() - local r = region.create(0,0, "ocean") - region.create(1,0, "ocean") - local r2 = region.create(2,0, "ocean") - local f = faction.create("noreply@eressea.de", "human", "de") - - -- u1 is at the limit and moves - local s1 = ship.create(r, "boat") - local u1 = unit.create(f, r, 5) - u1.ship = s1 - u1:set_skill("sailing", 10) - u1:clear_orders() - u1:add_order("NACH O O") - - -- u2 has too many people - local s2 = ship.create(r, "boat") - local u2 = unit.create(f, r, 6) - u2.ship = s2 - u2:set_skill("sailing", 10) - u2:clear_orders() - u2:add_order("NACH O O") - - -- u4 has too much stuff - local s4 = ship.create(r, "boat") - local u4 = unit.create(f, r, 5) - u4.ship = s4 - u4:set_skill("sailing", 10) - u4:add_item("sword", 1) - u4:clear_orders() - u4:add_order("NACH O O") - - process_orders() - --- print(s.region, u.region, r2) - assert_equal(r2, u1.region, "boat with 5 humans did not move") - assert_not_equal(r2, u2.region, "boat with too many people has moved") - assert_not_equal(r2, u4.region, "boat with too much cargo has moved") -end - -function test_levitate() - local r = region.create(0,0, "plain") - local f = faction.create("noreply@eressea.de", "human", "de") - local u = unit.create(f, r, 2) - local s = ship.create(r, "boat") - u.ship = s - u.age = 20 - u:set_skill("sailing", 5) - u:add_item("money", 100) - u:clear_orders() - u:add_order("ARBEITE") - levitate_ship(u.ship, u, 2, 1) - assert_equal(32, u.ship.flags) - process_orders() - assert_equal(0, u.ship.flags) -end - -function test_terrains() - local terrains = { "hell", "wall1", "corridor1" } - for k,v in ipairs(terrains) do - local r = region.create(k, k, v) - assert_not_equal(nil, r) - end -end - -function test_races() - local races = { "wolf", "orc", "human", "demon" } - for k,v in ipairs(races) do - local f = faction.create("noreply@eressea.de", "human", "de") - assert_not_equal(nil, f) - end -end - -function test_can_give_person() - local r = region.create(0, 0, "plain") - local f1 = faction.create("noreply@eressea.de", "human", "de") - local f2 = faction.create("noreply@eressea.de", "human", "de") - local u1 = unit.create(f1, r, 10) - local u2 = unit.create(f2, r, 10) - u1.faction.age = 10 - u2.faction.age = 10 - u1:add_item("money", 500) - u2:add_item("money", 500) - u2:clear_orders() - u2:add_order("GIB ".. itoa36(u1.id) .. " 1 PERSON") - u2:add_order("HELFE ".. itoa36(f1.id) .. " GIB") - u1:add_order("HELFE ".. itoa36(f2.id) .. " GIB") - u1:add_order("KONTAKTIERE ".. itoa36(u2.id)) - process_orders() - assert_equal(9, u2.number) - assert_equal(11, u1.number) -end - -function test_no_uruk() - local f1 = faction.create("noreply@eressea.de", "uruk", "de") - assert_equal(f1.race, "orc") -end - -function test_snowman() - local r = region.create(0, 0, "glacier") - local f = faction.create("noreply@eressea.de", "human", "de") - local u = unit.create(f, r, 1) - u:add_item("snowman", 1) - u:clear_orders() - u:add_order("BENUTZEN 1 Schneemann") - process_orders() - for u2 in r.units do - if u2.id~=u.id then - assert_equal(u2.race, "snowman") - u = nil - break - end - end - assert_equal(nil, u) -end - -function test_block_movement() - eressea.settings.set("rules.guard.base_stop_prob", "0.3") - eressea.settings.set("rules.guard.amulet_stop_prob", "0.0") - eressea.settings.set("rules.guard.skill_stop_prob", "0.1") - - local r0 = region.create(0, 0, "plain") - local r1 = region.create(1, 0, "plain") - local r2 = region.create(2, 0, "plain") - local f1, f2 = two_factions() - f1.age=20 - f2.age=20 - - local u11 = one_unit(r1, f1) - local u2 = { } - for i = 1, 20 do - u2[i] = one_unit(r0, f2) - end - - u11:add_item("sword", 1) - u11:add_item("money", 1) - u11:set_skill("melee", 1) - u11:set_skill("perception", 7) - u11:clear_orders() - u11:add_order("BEWACHEN") - - process_orders() - - for i, u in ipairs(u2) do - u:add_item("horse", 1) - u:set_skill("riding", 1) - u:clear_orders() - u:add_order("NACH o o") - end - - u2[1]:set_skill("stealth", 8) - - process_orders() - - assert_equal(r2, u2[1].region, "nobody should see me") - for i, u in ipairs(u2) do - if i > 1 then - assert_equal(r1, u.region, "perception +7 should always stop me") - end - end -end - - - -function test_block_movement_aots() - eressea.settings.set("rules.guard.base_stop_prob", "0.0") - eressea.settings.set("rules.guard.skill_stop_prob", "1.0") - eressea.settings.set("rules.guard.amulet_stop_prob", "1.1") - - local r0 = region.create(0, 0, "plain") - local r1 = region.create(1, 0, "plain") - local r2 = region.create(2, 0, "plain") - local f1, f2 = two_factions() - f1.age=20 - f2.age=20 - - local u11, u12 = two_units(r1, f1, f1) - local u21, u22 = two_units(r0, f2, f2) - - for i, u in ipairs ({ u11, u12 }) do - u:add_item("sword", 1) - u:add_item("money", 1) - u:set_skill("melee", 1) - u:clear_orders() - u:add_order("BEWACHEN") - end - - process_orders() - - for i, u in ipairs ({ u21, u22 }) do - u:add_item("horse", 1) - u:set_skill("riding", 1) - u:clear_orders() - u:add_order("NACH o o") - end - - u12:add_item("aots", 10) - u22:set_skill("stealth", 1) - - process_orders() - - assert_equal(r1, u21.region, "unit with amulet should stop me") - assert_equal(r2, u22.region, "nobody should see me") -end - -function test_stonegolems() - local r0 = region.create(0, 0, "plain") - local f1 = faction.create("noreply@eressea.de", "stonegolem", "de") - local u1 = unit.create(f1, r0, 1) - local u2 = unit.create(f1, r0, 2) - local c1 = building.create(r0, "castle") - - c1.size = 226 - - u1:set_skill("building", 1) - u2:set_skill("building", 1) - --- test that no server crash occur - u1:clear_orders() - u1:add_order("Mache Burg") - process_orders() - assert_equal(0 ,u1.number, "There shoud be no Stone Golems") --- end test server crash - --- test that Stone Golems build for four stones - u2:clear_orders() - u2:add_order("MACHE 4 BURG " .. itoa36(c1.id)) - process_orders() - assert_equal(230, c1.size, "resulting size should be 230") - assert_equal(1 ,u2.number, "There shoud be one Stone Golems") --- end test Stone Golems four stones -end - -function test_only_building_owner_can_set_not_paid() - local r = region.create(0, 0, "plain") - local f = faction.create("noreply@eressea.de", "human", "de") - local u1 = unit.create(f, r, 1) - local u2 = unit.create(f, r, 1) - local mine = building.create(r, "mine") - mine.size = 2 - u1:add_item("money", 500) - u1.building = mine - u2.building = mine - u1:clear_orders() - u2:clear_orders() --- Test that Bezahle nicht is working - u1:add_order("Bezahle nicht") - process_orders() - assert_equal(500, u1:get_item("money")) - u1:clear_orders() --- Test that bug fix 0001976 is working --- Bezahle nicht is not working - u2:add_order("Bezahle nicht") - process_orders() - assert_equal(0, u1:get_item("money")) -end diff --git a/scripts/tests/faction.lua b/scripts/tests/faction.lua index a6a07a6e1..f0cd9335c 100644 --- a/scripts/tests/faction.lua +++ b/scripts/tests/faction.lua @@ -1,3 +1,5 @@ +require "lunit" + module ('tests.eressea.faction', package.seeall, lunit.testcase) local f @@ -5,24 +7,25 @@ local f function setup() conf = [[{ "races": { - "human" : {} + "human" : {} } }]] eressea.config.reset() assert(eressea.config.parse(conf)==0) - f = faction.create("faction@eressea.de", "human", "de") + f = faction.create("faction@eressea.de", "human", "de") + assert(f~=nil) end function test_faction_flags() - assert_equal(0, f.flags) - f.flags = 42 - assert_equal(42, f.flags) + assert_equal(0, f.flags) + f.flags = 42 + assert_equal(42, f.flags) end function test_get_faction() - assert_equal(f, get_faction(f.id)) - assert_equal(f, faction.get(f.id)) - local nf = f.id - if nf>1 then nf = nf - 1 else nf = 1 end - assert_equal(nil, faction.get(nf)) + assert_equal(f, get_faction(f.id)) + assert_equal(f, faction.get(f.id)) + local nf = f.id + if nf>1 then nf = nf - 1 else nf = 1 end + assert_equal(nil, faction.get(nf)) end diff --git a/scripts/tests/init.lua b/scripts/tests/init.lua index deb3e1a89..baa8dbef4 100644 --- a/scripts/tests/init.lua +++ b/scripts/tests/init.lua @@ -1,9 +1,11 @@ -- new tests 2014-06-11 -require 'tests.pool' -require 'tests.settings' require 'tests.config' require 'tests.faction' require 'tests.locale' -require 'tests.regions' -require 'tests.study' require 'tests.movement' +require 'tests.pool' +require 'tests.regions' +require 'tests.settings' +require 'tests.study' +require 'tests.laws' +require 'tests.bindings' diff --git a/scripts/tests/laws.lua b/scripts/tests/laws.lua new file mode 100644 index 000000000..f0fef15a9 --- /dev/null +++ b/scripts/tests/laws.lua @@ -0,0 +1,114 @@ +require "lunit" + +module("tests.laws", package.seeall, lunit.testcase) + +function setup() + eressea.free_game() + conf = [[{ + "races": { + "human" : {} + }, + "terrains" : { + "plain": { "flags" : [ "land", "walk", "sail" ] } + }, + "keywords" : { + "de": { + "attack" : "ATTACKIERE", + "maketemp" : "MACHETEMP", + "end" : "ENDE", + "recruit" : "REKRUTIERE" + } + }, + "buildings" : { + "castle" : {} + } + }]] + + eressea.config.reset() + eressea.config.parse(conf) +end + +function test_force_leave_on() + local r = region.create(0, 0, "plain") + local f1 = faction.create("owner@eressea.de") + local f2 = faction.create("guest@eressea.de") + local u1 = unit.create(f1, r, 1) + local u2 = unit.create(f2, r, 1) + local b1 = building.create(r, "castle") + u1.building = b1 + u2.building = b1 + eressea.settings.set("rules.owners.force_leave", "2") + process_orders() + assert_equal(b1, u1.building) + assert_equal(nil, u2.building) +end + +function test_force_leave_off() + local r = region.create(0, 0, "plain") + local f1 = faction.create("owner@eressea.de") + local f2 = faction.create("guest@eressea.de") + local u1 = unit.create(f1, r, 1) + local u2 = unit.create(f2, r, 1) + local b1 = building.create(r, "castle") + u1.building = b1 + u2.building = b1 + eressea.settings.set("rules.owners.force_leave", "0") + process_orders() + assert_equal(b1, u1.building) + assert_equal(b1, u2.building) +end + +function test_make_temp() + local r = region.create(0, 0, "plain") + local f1 = faction.create("owner@eressea.de", "human", "de") + local u1 = unit.create(f1, r, 10) + local u, u2 + + u1.building = building.create(r, "castle") + u1.status = 1 + u1:clear_orders() + u1:add_order("MACHETEMP 1 Hodor") + u1:add_order("REKRUTIERE 1") + u1:add_order("ENDE") + process_orders() + for u in r.units do + if u~=u1 then + u2 = u + break + end + end + assert_not_equal(nil, u2) + assert_not_equal(nil, u2.building) + assert_equal(1, u2.number) + assert_equal(1, u2.status) + assert_equal("Hodor", u2.name) +end + +function test_force_leave_postcombat() + local r = region.create(0, 0, "plain") + local f1 = faction.create("owner@eressea.de", "human", "de") + local f2 = faction.create("guest@eressea.de", "human", "de") + local u1 = unit.create(f1, r, 10) + local u2 = unit.create(f2, r, 10) + local u, u3 + local b1 = building.create(r, "castle") + u1.building = b1 + u2.building = b1 + eressea.settings.set("rules.owners.force_leave", "1") + u1:clear_orders() + u1:add_order("ATTACKIERE " .. itoa36(u2.id)) + u2:clear_orders() + u2:add_order("MACHETEMP 2 Hodor") + u2:add_order("REKRUTIERE 1") + u2:add_order("ENDE") + process_orders() + for u in r.units do + if u~=u1 and u~=u2 then + u3 = u + break + end + end + assert_not_equal(nil, u3) + assert_equal(nil, u3.building) + assert_equal(1, u3.number) +end diff --git a/scripts/tests/magicbag.lua b/scripts/tests/magicbag.lua new file mode 100644 index 000000000..4ca5e6ae5 --- /dev/null +++ b/scripts/tests/magicbag.lua @@ -0,0 +1,58 @@ +require "lunit" + +module("tests.magicbag", package.seeall, lunit.testcase) + +local u + +function setup() + eressea.free_game() + u = unit.create(faction.create("test@example.com", "human", "de"), region.create(0, 0, "plain"), 1) +end + +function test_magicbag_weight() + assert_equal(1000, u.weight) + u:add_item("log", 10) + assert_equal(6000, u.weight) + u:add_item("magicbag", 1) + assert_equal(1100, u.weight) +end + +function test_magicbag_no_stone() + assert_equal(1000, u.weight) + u:add_item("stone", 1) + assert_equal(7000, u.weight) + u:add_item("magicbag", 1) + assert_equal(7100, u.weight) +end + +function test_magicbag_limit_200ge() + assert_equal(1000, u.weight) + u:add_item("log", 100) + assert_equal(51000, u.weight) + u:add_item("magicbag", 1) + assert_equal(31100, u.weight) +end + +function test_magicbag_no_carts() + assert_equal(1000, u.weight) + u:add_item("cart", 1) + assert_equal(5000, u.weight) + u:add_item("magicbag", 1) + assert_equal(5100, u.weight) +end + +function test_magicbag_no_catapult() + assert_equal(1000, u.weight) + u:add_item("catapult", 1) + assert_equal(11000, u.weight) + u:add_item("magicbag", 1) + assert_equal(11100, u.weight) +end + +function test_magicbag_no_horses() + assert_equal(1000, u.weight) + u:add_item("horse", 1) + assert_equal(6000, u.weight) + u:add_item("magicbag", 1) + assert_equal(6100, u.weight) +end diff --git a/scripts/tests/movement.lua b/scripts/tests/movement.lua index e27831cc8..110b5b2a2 100644 --- a/scripts/tests/movement.lua +++ b/scripts/tests/movement.lua @@ -4,7 +4,6 @@ module("tests.movement", package.seeall, lunit.testcase) function setup() eressea.free_game() - eressea.settings.set("nmr.removenewbie", "0") eressea.settings.set("nmr.timeout", "0") eressea.settings.set("rules.ships.storms", "0") conf = [[{ diff --git a/scripts/eressea/tests/orders.lua b/scripts/tests/orders.lua similarity index 89% rename from scripts/eressea/tests/orders.lua rename to scripts/tests/orders.lua index af1ba8863..d9443c9c4 100644 --- a/scripts/eressea/tests/orders.lua +++ b/scripts/tests/orders.lua @@ -16,7 +16,6 @@ function setup() u = _G.unit.create(f, r, 1) u:clear_orders() eressea.settings.set("rules.economy.food", "4") - eressea.settings.set("nmr.removenewbie", "0") eressea.settings.set("nmr.timeout", "0") eressea.settings.set("NewbieImmunity", "0") end @@ -117,27 +116,6 @@ function test_process_make() assert_equal(1, u:get_item('log')) end -function test_process_study() - u:add_order("LERNEN Holzfaellen") - eressea.process.update_long_order() - eressea.process.study() - x, y = u.faction:get_origin() - assert_equal(1, u:get_skill('forestry')) -end - -function test_process_teach() - eressea.settings.set("study.random_progress", "0") - u:set_skill('forestry', 3) - u2 = _G.unit.create(f, r, 10) - u2:clear_orders() - u2:set_skill('forestry', 1) - u2:add_order("LERNEN Holzfaellen") - u:add_order("LEHREN " .. _G.itoa36(u2.id)) - eressea.process.update_long_order() - eressea.process.study() - assert_equal(2, u2:get_skill('forestry')) -end - function test_process_move() r2 = _G.region.create(1, 0, 'plain') u:add_order('NACH O') diff --git a/scripts/tests/pool.lua b/scripts/tests/pool.lua index 2ac9c87f2..bf32eda87 100644 --- a/scripts/tests/pool.lua +++ b/scripts/tests/pool.lua @@ -6,7 +6,6 @@ function setup() eressea.game.reset() eressea.config.reset() eressea.settings.set("rules.economy.food", "0") - eressea.settings.set("nmr.removenewbie", "0") eressea.settings.set("nmr.timeout", "0") eressea.settings.set("rules.magic.playerschools", "") conf = [[{ @@ -61,6 +60,7 @@ end function test_give_divisor() eressea.settings.set("rules.items.give_divisor", 2) + eressea.settings.set("GiveRestriction", 0) local r = region.create(1, 1, "plain") local f1 = faction.create("test@example.com", "human", "de") local f2 = faction.create("test@example.com", "human", "de") diff --git a/scripts/tests/storage.lua b/scripts/tests/storage.lua new file mode 100644 index 000000000..cf496224c --- /dev/null +++ b/scripts/tests/storage.lua @@ -0,0 +1,31 @@ +require "lunit" + +module("tests.storage", package.seeall, lunit.testcase) + +function setup() + eressea.free_game() +end + +function test_store_unit() + local r = region.create(0, 0, "plain") + local f = faction.create("noreply15@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + local fid = f.id + u:add_item("money", u.number * 100) + local filename = config.basepath .. "/data/test.dat" + store = storage.create(filename, "wb") + assert_not_equal(store, nil) + store:write_unit(u) + store:close() + eressea.free_game() + -- recreate world: + r = region.create(0, 0, "plain") + f = faction.create("noreply16@eressea.de", "human", "de") + f.id = fid + store = storage.create(filename, "rb") + assert_not_nil(store) + u = store:read_unit() + store:close() + assert_not_nil(u) + assert_equal(u:get_item("money"), u.number * 100) +end diff --git a/scripts/tests/study.lua b/scripts/tests/study.lua index 7d27cc7d2..e5ab84018 100644 --- a/scripts/tests/study.lua +++ b/scripts/tests/study.lua @@ -7,7 +7,8 @@ function setup() "races" : { "human" : {} }, "terrains" : { "plain" : { "flags" : [ "land" ] } }, "keywords" : { "de" : { "study": "LERNEN" } }, - "skills" : { "de": { "alchemy" : "Alchemie", "crossbow" : "Armbrust" } } + "skills" : { "de": { "alchemy" : "Alchemie", "crossbow" : "Armbrust" } }, + "spells" : { "fireball" : { "syntax" : "u+" } } }]] eressea.game.reset() eressea.config.reset(); @@ -36,3 +37,17 @@ function test_study_expensive() assert_equal(1, u:get_skill("alchemy")) assert_equal(0, u:get_item("money")) end + +function test_unit_spells() + local r = region.create(0, 0, "plain") + local f = faction.create("test@example.com", "human", "de") + local u = unit.create(f, r, 1) + u.magic = "gray" + u:set_skill("magic", 1) + u:add_spell("toast") + assert_equal(nil, u.spells) + u:add_spell("fireball", 2) + local sp = u.spells() + assert_equal("fireball", sp.name) + assert_equal(2, sp.level) +end diff --git a/share/ubuntu-12_04.supp b/share/ubuntu-12_04.supp new file mode 100644 index 000000000..3d6ae2974 --- /dev/null +++ b/share/ubuntu-12_04.supp @@ -0,0 +1,37 @@ +# old zlib version +{ + zlib1g-dev-1:1.2.3.4.dfsg + Memcheck:Cond + fun:inflateReset2 + fun:inflateInit2_ + obj:/usr/lib/x86_64-linux-gnu/libxml2.so.2.8.0 + fun:__libxml2_xzread + obj:/usr/lib/x86_64-linux-gnu/libxml2.so.2.8.0 + fun:xmlParserInputBufferGrow + fun:xmlParserInputGrow + obj:/usr/lib/x86_64-linux-gnu/libxml2.so.2.8.0 + fun:xmlParseDocument + obj:/usr/lib/x86_64-linux-gnu/libxml2.so.2.8.0 + fun:read_xml + fun:init_data +} + +# https://sourceware.org/bugzilla/show_bug.cgi?id=14404 +{ + glibc-bug-14404-1 + Memcheck:Addr8 + fun:__GI___strncasecmp_l + fun:____strtod_l_internal +} +{ + glibc-bug-14404-2 + Memcheck:Cond + fun:__GI___strncasecmp_l + fun:____strtod_l_internal +} +{ + glibc-bug-14404-3 + Memcheck:Value8 + fun:__GI___strncasecmp_l + fun:____strtod_l_internal +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index de25db3da..27c85c8de 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,18 +13,31 @@ include_directories (${TOLUA_INCLUDE_DIR}) include_directories (${BSON_INCLUDE_DIR}) include_directories (${INIPARSER_INCLUDE_DIR}) -IF(CMAKE_COMPILER_IS_GNUCC) - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pedantic -Wall -Werror -Wno-unknown-pragmas -Wstrict-prototypes -Wpointer-arith -Wno-char-subscripts -Wno-long-long") +IF(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wconversion -Wno-sign-conversion") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pedantic -Wsign-compare -Wall -Werror -Wno-unknown-pragmas -Wstrict-prototypes -Wpointer-arith -Wno-char-subscripts -Wno-long-long") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error=unused-but-set-variable") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -DHAVE__BOOL") -elseif(MSVC) - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4 /WX /MP") +ELSEIF(MSVC) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Wall /WX /MP") set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /NODEFAULTLIB:libc.lib /NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:libcd.lib /NODEFAULTLIB:libcmtd.lib /NODEFAULTLIB:msvcrt.lib") set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /NODEFAULTLIB:libc.lib /NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:libcd.lib /NODEFAULTLIB:libcmtd.lib /NODEFAULTLIB:msvcrtd.lib") -ELSE(CMAKE_COMPILER_IS_GNUCC) - MESSAGE(STATUS "Unknown compiler ${CMAKE_C_COMPILER_ID}") -ENDIF(CMAKE_COMPILER_IS_GNUCC) +ELSE() + MESSAGE(STATUS "unknown compiler ${CMAKE_C_COMPILER_ID}") +ENDIF() + +IF(CMAKE_COMPILER_IS_CLANG) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wtautological-compare -Weverything") + MESSAGE(STATUS "compiler is clang: ${CMAKE_C_COMPILER_ID}") +ELSEIF(CMAKE_COMPILER_IS_GCC) + EXECUTE_PROCESS(COMMAND ${CMAKE_C_COMPILER} -dumpversion + OUTPUT_VARIABLE GCC_VERSION) + IF (GCC_VERSION VERSION_GREATER 4.9) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wfloat-conversion") + ENDIF() +ENDIF(CMAKE_COMPILER_IS_CLANG) add_subdirectory(util) add_subdirectory(kernel) @@ -80,6 +93,7 @@ set (ERESSEA_SRC skill.c json.c creport.c + jsreport.c economy.c give.c items.c @@ -177,10 +191,14 @@ set(TESTS_SRC market.test.c move.test.c skill.test.c + spells.test.c + spy.test.c upkeep.test.c + spells/magicresistance.test.c ${ATTRIBUTES_TESTS} ${UTIL_TESTS} ${KERNEL_TESTS} + ${ITEMS_TESTS} ) add_executable(test_eressea ${TESTS_SRC}) diff --git a/src/attributes/movement.c b/src/attributes/movement.c index 662affdf3..beb3998f0 100644 --- a/src/attributes/movement.c +++ b/src/attributes/movement.c @@ -25,6 +25,9 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include +#include +#include + static void write_movement(const attrib * a, const void *owner, struct storage *store) { @@ -65,7 +68,9 @@ void set_movement(attrib ** alist, int type) static int age_speedup(attrib * a) { if (a->data.sa[0] > 0) { - a->data.sa[0] = a->data.sa[0] - a->data.sa[1]; + assert(a->data.sa[0] - a->data.sa[1] >= SHRT_MIN); + assert(a->data.sa[0] - a->data.sa[1] <= SHRT_MAX); + a->data.sa[0] = (short)(a->data.sa[0] - a->data.sa[1]); } return (a->data.sa[0] > 0) ? AT_AGE_KEEP : AT_AGE_REMOVE; } diff --git a/src/battle.c b/src/battle.c index d139280be..d45cf02e7 100644 --- a/src/battle.c +++ b/src/battle.c @@ -307,7 +307,7 @@ fighter *select_corpse(battle * b, fighter * af) maxcasualties += s->casualties; } } - di = rng_int() % maxcasualties; + di = (int)(rng_int() % maxcasualties); for (s = b->sides; s != b->sides + b->nsides; ++s) { for (df = s->fighters; df; df = df->next) { /* Geflohene haben auch 0 hp, drfen hier aber nicht ausgewhlt @@ -431,7 +431,7 @@ static int get_row(const side * s, int row, const side * vs) return result; } -int get_unitrow(const fighter * af, const side * vs) +static int get_unitrow(const fighter * af, const side * vs) { int row = statusrow(af->status); if (vs == NULL) { @@ -487,7 +487,7 @@ contest_classic(int skilldiff, const armor_type * ar, const armor_type * sh) vw = (int)(100 - ((100 - vw) * mod)); do { - p = rng_int() % 100; + p = (int)(rng_int() % 100); vw -= p; } while (vw >= 0 && p >= 90); return (vw <= 0); @@ -901,7 +901,9 @@ static void rmtroop(troop dt) rmfighter(df, 1); assert(dt.index >= 0 && dt.index < df->unit->number); - df->person[dt.index] = df->person[df->alive - df->removed]; + if (dt.index!=df->alive-df->removed) { + df->person[dt.index] = df->person[df->alive - df->removed]; + } if (df->removed) { df->person[df->alive - df->removed] = df->person[df->alive]; } @@ -1019,7 +1021,8 @@ static int natural_armor(unit * du) static int *bonus = 0; int an = u_race(du)->armor; if (bonus == 0) { - bonus = calloc(sizeof(int), num_races); + assert(num_races > 0); + bonus = calloc((size_t)num_races, sizeof(int)); } if (bonus[u_race(du)->index] == 0) { bonus[u_race(du)->index] = @@ -1282,11 +1285,19 @@ terminate(troop dt, troop at, int type, const char *damage, bool missile) } assert(dt.index < du->number); - df->person[dt.index].hp -= rda; - if (u_race(au) == get_race(RC_DAEMON)) { - vampirism(at, rda); - } + if (rda>0) { + df->person[dt.index].hp -= rda; + if (u_race(au) == get_race(RC_DAEMON)) { + vampirism(at, rda); + } + if (b->turn>1) { + /* someone on the ship got damaged, damage the ship */ + ship *sh = du->ship ? du->ship : leftship(du); + if (sh) + fset(sh, SF_DAMAGED); + } + } if (df->person[dt.index].hp > 0) { /* Hat berlebt */ if (bdebug) { fprintf(bdebug, "Damage %d, armor %d: %d -> %d HP\n", @@ -1498,7 +1509,7 @@ troop select_enemy(fighter * af, int minrow, int maxrow, int select) if (enemies <= 0) return no_troop; - selected = rng_int() % enemies; + selected = (int)(rng_int() % enemies); for (si = 0; as->enemies[si]; ++si) { side *ds = as->enemies[si]; fighter *df; @@ -1686,7 +1697,7 @@ void do_combatmagic(battle * b, combatmagic_t was) level = eff_skill(mage, SK_MAGIC, r); if (level > 0) { - float power; + double power; const spell *sp; const struct locale *lang = mage->faction->locale; order *ord; @@ -1762,7 +1773,7 @@ void do_combatmagic(battle * b, combatmagic_t was) } } -static int cast_combatspell(troop at, const spell * sp, int level, float force) +static int cast_combatspell(troop at, const spell * sp, int level, double force) { castorder co; @@ -1785,7 +1796,7 @@ static void do_combatspell(troop at) region *r = b->region; quicklist *ql; int level, qi; - float power; + double power; int fumblechance = 0; order *ord; int sl; @@ -1858,9 +1869,9 @@ static void do_extra_spell(troop at, const att * a) log_error("spell '%s' has no function.\n", sp->sname); } else { - int level = a->level; + double force = a->level * MagicPower(); assert(a->level > 0); - cast_combatspell(at, sp, level, level * MagicPower()); + cast_combatspell(at, sp, a->level, force); } } @@ -2291,11 +2302,12 @@ void do_attack(fighter * af) for (apr = 0; apr != attacks; ++apr) { int a; - for (a = 0; a != 10 && u_race(au)->attack[a].type != AT_NONE; ++a) { + for (a = 0; a < RACE_ATTACKS && u_race(au)->attack[a].type != AT_NONE; ++a) { if (apr > 0) { /* Wenn die Waffe nachladen muss, oder es sich nicht um einen * Waffen-Angriff handelt, dann gilt der Speed nicht. */ - if (u_race(au)->attack[a].type != AT_STANDARD) + /* FIXME allow multiple AT_NATURAL attacks? */ + if (u_race(au)->attack[a].type != AT_STANDARD) continue; else { weapon *wp = preferred_weapon(ta, true); @@ -2327,8 +2339,9 @@ void do_regenerate(fighter * af) ta.index = af->fighting; while (ta.index--) { - af->person[ta.index].hp += effskill(au, SK_STAMINA); - af->person[ta.index].hp = _min(unit_max_hp(au), af->person[ta.index].hp); + struct person *p = af->person + ta.index; + p->hp += effskill(au, SK_STAMINA); + p->hp = _min(unit_max_hp(au), p->hp); } } @@ -2458,7 +2471,7 @@ troop select_ally(fighter * af, int minrow, int maxrow, int allytype) if (!allies) { return no_troop; } - allies = rng_int() % allies; + allies = (int)(rng_int() % allies); for (ds = b->sides; ds != b->sides + b->nsides; ++ds) { if ((allytype == ALLY_ANY && helping(as, ds)) || (allytype == ALLY_SELF @@ -2486,7 +2499,7 @@ troop select_ally(fighter * af, int minrow, int maxrow, int allytype) static int loot_quota(const unit * src, const unit * dst, const item_type * type, int n) { - static float divisor = -1; + static double divisor = -1; if (dst && src && src->faction != dst->faction) { if (divisor < 0) { divisor = get_param_flt(global.parameters, "rules.items.loot_divisor", 1); @@ -2517,8 +2530,8 @@ static void loot_items(fighter * corpse) return; while (itm) { - float lootfactor = dead / (float)u->number; /* only loot the dead! */ - int maxloot = (int)(itm->number * lootfactor); + float lootfactor = (float)dead / (float)u->number; /* only loot the dead! */ + int maxloot = (int)((float)itm->number * lootfactor); if (maxloot > 0) { int i = _min(10, maxloot); for (; i != 0; --i) { @@ -2712,13 +2725,6 @@ static void aftermath(battle * b) if (flags) { fset(du, flags); } - if (sum_hp + df->run.hp < du->hp) { - /* someone on the ship got damaged, damage the ship */ - ship *sh = du->ship ? du->ship : leftship(du); - if (sh) - fset(sh, SF_DAMAGED); - } - if (df->alive && df->alive == du->number) { du->hp = sum_hp; continue; /* nichts passiert */ @@ -2860,7 +2866,7 @@ static void aftermath(battle * b) float dmg = get_param_flt(global.parameters, "rules.ship.damage.battleround", 0.05F); - damage_ship(sh, dmg * n); + damage_ship(sh, dmg * (float)n); freset(sh, SF_DAMAGED); } } @@ -2961,19 +2967,19 @@ static void print_header(battle * b) side *s; char *bufp = zText; size_t size = sizeof(zText) - 1; - int bytes; + size_t bytes; for (s = b->sides; s != b->sides + b->nsides; ++s) { fighter *df; for (df = s->fighters; df; df = df->next) { if (is_attacker(df)) { if (first) { - bytes = (int)strlcpy(bufp, ", ", size); + bytes = strlcpy(bufp, ", ", size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } if (lastf) { - bytes = (int)strlcpy(bufp, (const char *)lastf, size); + bytes = strlcpy(bufp, (const char *)lastf, size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); first = true; @@ -2987,18 +2993,18 @@ static void print_header(battle * b) } } if (first) { - bytes = (int)strlcpy(bufp, " ", size); + bytes = strlcpy(bufp, " ", size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); - bytes = (int)strlcpy(bufp, (const char *)LOC(f->locale, "and"), size); + bytes = strlcpy(bufp, (const char *)LOC(f->locale, "and"), size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); - bytes = (int)strlcpy(bufp, " ", size); + bytes = strlcpy(bufp, " ", size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } if (lastf) { - bytes = (int)strlcpy(bufp, (const char *)lastf, size); + bytes = strlcpy(bufp, (const char *)lastf, size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } @@ -3173,7 +3179,7 @@ side * get_side(battle * b, const struct unit * u) return 0; } -side * find_side(battle * b, const faction * f, const group * g, int flags, const faction * stealthfaction) +side * find_side(battle * b, const faction * f, const group * g, unsigned int flags, const faction * stealthfaction) { side * s; static int rule_anon_battle = -1; @@ -3183,8 +3189,8 @@ side * find_side(battle * b, const faction * f, const group * g, int flags, cons } for (s = b->sides; s != b->sides + b->nsides; ++s) { if (s->faction == f && s->group == g) { - int s1flags = flags | SIDE_HASGUARDS; - int s2flags = s->flags | SIDE_HASGUARDS; + unsigned int s1flags = flags | SIDE_HASGUARDS; + unsigned int s2flags = s->flags | SIDE_HASGUARDS; if (rule_anon_battle && s->stealthfaction != stealthfaction) { continue; } @@ -3202,7 +3208,6 @@ fighter *make_fighter(battle * b, unit * u, side * s1, bool attack) weapon weapons[WMAX]; int owp[WMAX]; int dwp[WMAX]; - int w = 0; region *r = b->region; item *itm; fighter *fig = NULL; @@ -3227,7 +3232,7 @@ fighter *make_fighter(battle * b, unit * u, side * s1, bool attack) } /* Illusionen und Zauber kaempfen nicht */ - if (fval(u_race(u), RCF_ILLUSIONARY) || idle(u->faction) || u->number == 0) { + if (fval(u_race(u), RCF_ILLUSIONARY) || u->number == 0) { return NULL; } if (s1 == NULL) { @@ -3268,7 +3273,8 @@ fighter *make_fighter(battle * b, unit * u, side * s1, bool attack) fig->catmsg = -1; /* Freigeben nicht vergessen! */ - fig->person = (struct person*)calloc(fig->alive, sizeof(struct person)); + assert(fig->alive > 0); + fig->person = (struct person*)calloc((size_t)fig->alive, sizeof(struct person)); h = u->hp / u->number; assert(h); @@ -3327,7 +3333,7 @@ fighter *make_fighter(battle * b, unit * u, side * s1, bool attack) /* Fr alle Waffengattungen wird bestimmt, wie viele der Personen mit * ihr kmpfen knnten, und was ihr Wert darin ist. */ if (u_race(u)->battle_flags & BF_EQUIPMENT) { - int oi = 0, di = 0; + int oi = 0, di = 0, w = 0; for (itm = u->items; itm && w != WMAX; itm = itm->next) { const weapon_type *wtype = resource2weapon(itm->type->rtype); if (wtype == NULL || itm->number == 0) @@ -3342,8 +3348,9 @@ fighter *make_fighter(battle * b, unit * u, side * s1, bool attack) } assert(w != WMAX); } - fig->weapons = (weapon *)calloc(sizeof(weapon), w + 1); - memcpy(fig->weapons, weapons, w * sizeof(weapon)); + assert(w >= 0); + fig->weapons = (weapon *)calloc(sizeof(weapon), (size_t)(w + 1)); + memcpy(fig->weapons, weapons, (size_t)w * sizeof(weapon)); for (i = 0; i != w; ++i) { int j, o = 0, d = 0; @@ -3482,7 +3489,7 @@ fighter *make_fighter(battle * b, unit * u, side * s1, bool attack) int rnd; do { - rnd = rng_int() % 100; + rnd = (int)(rng_int() % 100); if (rnd >= 40 && rnd <= 69) p_bonus += 1; else if (rnd <= 89) @@ -3656,6 +3663,24 @@ static void free_fighter(fighter * fig) } +static void battle_free(battle * b) { + side *s; + + assert(b); + + for (s = b->sides; s != b->sides + b->nsides; ++s) { + fighter *fnext = s->fighters; + while (fnext) { + fighter *fig = fnext; + fnext = fig->next; + free_fighter(fig); + free(fig); + } + free_side(s); + } + free(b); +} + void free_battle(battle * b) { int max_fac_no = 0; @@ -3712,7 +3737,7 @@ static int battle_report(battle * b) faction *fac = bf->faction; char buf[32 * MAXSIDES]; char *bufp = buf; - int bytes; + size_t bytes; size_t size = sizeof(buf) - 1; message *m; @@ -3735,32 +3760,32 @@ static int battle_report(battle * b) char buffer[32]; if (komma) { - bytes = (int)strlcpy(bufp, ", ", size); + bytes = strlcpy(bufp, ", ", size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } slprintf(buffer, sizeof(buffer), "%s %2d(%s): ", loc_army, army_index(s), abbrev); - bytes = (int)strlcpy(bufp, buffer, size); + bytes = strlcpy(bufp, buffer, size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); for (r = FIGHT_ROW; r != NUMROWS; ++r) { if (alive[r]) { if (l != FIGHT_ROW) { - bytes = (int)strlcpy(bufp, "+", size); + bytes = strlcpy(bufp, "+", size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } while (k--) { - bytes = (int)strlcpy(bufp, "0+", size); + bytes = strlcpy(bufp, "0+", size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } sprintf(buffer, "%d", alive[r]); - bytes = (int)strlcpy(bufp, buffer, size); + bytes = strlcpy(bufp, buffer, size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); @@ -3921,7 +3946,6 @@ static bool start_battle(region * r, battle ** bp) unit *u; bool fighting = false; - /* list_foreach geht nicht, wegen flucht */ for (u = r->units; u != NULL; u = u->next) { if (fval(u, UFL_LONGACTION)) continue; @@ -4183,8 +4207,6 @@ static void battle_flee(battle * b) default: if ((fig->person[dt.index].flags & FL_HIT) == 0) continue; - if (b->turn <= 1) - continue; if (fig->person[dt.index].hp <= runhp) break; if (fig->person[dt.index].flags & FL_PANICED) { @@ -4211,6 +4233,52 @@ static void battle_flee(battle * b) } } +static bool is_enemy(battle *b, unit *u1, unit *u2) { + if (u1->faction != u2->faction) { + if (b) { + side *es, *s1 = 0, *s2 = 0; + for (es = b->sides; es != b->sides + b->nsides; ++es) { + if (!s1 && es->faction == u1->faction) s1 = es; + else if (!s2 && es->faction == u2->faction) s2 = es; + if (s1 && s2) break; + } + return enemy(s1, s2); + } + else { + return !help_enter(u1, u2); + } + } + return false; +} + +void force_leave(region *r, battle *b) { + unit *u; + + for (u = r->units; u; u = u->next) { + unit *uo = NULL; + if (u->building) { + uo = building_owner(u->building); + } + if (u->ship && r->land) { + uo = ship_owner(u->ship); + } + if (uo && is_enemy(b, uo, u)) { + message *msg = NULL; + if (u->building) { + msg = msg_message("force_leave_building", "unit owner building", u, uo, u->building); + } + else { + msg = msg_message("force_leave_ship", "unit owner ship", u, uo, u->ship); + } + if (msg) { + ADDMSG(&u->faction->msgs, msg); + } + leave(u, false); + } + } +} + + void do_battle(region * r) { battle *b = NULL; @@ -4282,6 +4350,9 @@ void do_battle(region * r) /* Auswirkungen berechnen: */ aftermath(b); + if (rule_force_leave(FORCE_LEAVE_POSTCOMBAT)) { + force_leave(b->region, b); + } /* Hier ist das Gefecht beendet, und wir knnen die * Hilfsstrukturen * wieder lschen: */ @@ -4290,21 +4361,3 @@ void do_battle(region * r) } } -void battle_free(battle * b) { - side *s; - - assert(b); - - for (s = b->sides; s != b->sides + b->nsides; ++s) { - fighter *fnext = s->fighters; - while (fnext) { - fighter *fig = fnext; - fnext = fig->next; - free_fighter(fig); - free(fig); - } - free_side(s); - } - free(b); -} - diff --git a/src/battle.h b/src/battle.h index d144da30d..618850d31 100644 --- a/src/battle.h +++ b/src/battle.h @@ -130,13 +130,13 @@ extern "C" { } weapon; /*** fighter::person::flags ***/ -#define FL_TIRED 1 +#define FL_TIRED 1 #define FL_DAZZLED 2 /* durch Untote oder Dmonen eingeschchtert */ #define FL_PANICED 4 #define FL_COURAGE 8 /* Helden fliehen nie */ #define FL_SLEEPING 16 -#define FL_STUNNED 32 /* eine Runde keinen Angriff */ -#define FL_HIT 64 /* the person at attacked */ +#define FL_STUNNED 32 /* eine Runde keinen Angriff */ +#define FL_HIT 64 /* the person at attacked */ typedef struct troop { struct fighter *fighter; @@ -225,9 +225,7 @@ extern "C" { extern const troop no_troop; /* BEGIN battle interface */ - void battle_init(battle * b); - void battle_free(battle * b); - side * find_side(battle * b, const struct faction * f, const struct group * g, int flags, const struct faction * stealthfaction); + side * find_side(battle * b, const struct faction * f, const struct group * g, unsigned int flags, const struct faction * stealthfaction); side * get_side(battle * b, const struct unit * u); fighter * get_fighter(battle * b, const struct unit * u); /* END battle interface */ @@ -251,11 +249,10 @@ extern "C" { extern int hits(troop at, troop dt, weapon * awp); extern void damage_building(struct battle *b, struct building *bldg, int damage_abs); - extern struct quicklist *fighters(struct battle *b, const struct side *vs, + struct quicklist *fighters(struct battle *b, const struct side *vs, int minrow, int maxrow, int mask); - extern int count_allies(const struct side *as, int minrow, int maxrow, + int count_allies(const struct side *as, int minrow, int maxrow, int select, int allytype); - extern int get_unitrow(const struct fighter *af, const struct side *vs); extern bool helping(const struct side *as, const struct side *ds); extern void rmfighter(fighter * df, int i); extern struct fighter *select_corpse(struct battle *b, struct fighter *af); @@ -273,6 +270,7 @@ extern "C" { const struct group * g, unsigned int flags, const struct faction * stealthfaction); int skilldiff(troop at, troop dt, int dist); + void force_leave(struct region *r, struct battle *b); #ifdef __cplusplus } diff --git a/src/bind_building.c b/src/bind_building.c index 8b89d2618..714b915dd 100644 --- a/src/bind_building.c +++ b/src/bind_building.c @@ -1,4 +1,4 @@ -/* +/* +-------------------+ | | Enno Rehling | Eressea PBEM host | Christian Schlittchen @@ -20,6 +20,7 @@ without prior permission by the authors of Eressea. #include #include +#include #include #include @@ -114,7 +115,7 @@ static int tolua_building_set_name(lua_State * L) static int tolua_building_get_size(lua_State * L) { building *self = (building *)tolua_tousertype(L, 1, 0); - tolua_pushnumber(L, self->size); + lua_pushinteger(L, self->size); return 1; } @@ -145,7 +146,7 @@ static int tolua_building_get_units(lua_State * L) static int tolua_building_get_id(lua_State * L) { building *self = (building *)tolua_tousertype(L, 1, 0); - tolua_pushnumber(L, (lua_Number)self->no); + lua_pushinteger(L, self->no); return 1; } @@ -190,6 +191,12 @@ static int tolua_building_create(lua_State * L) { region *r = (region *)tolua_tousertype(L, 1, 0); const char *bname = tolua_tostring(L, 2, 0); + if (!r) { + log_error("building.create expects a region as argument 1"); + } + if (!bname) { + log_error("building.create expects a name as argument 2"); + } if (bname) { const building_type *btype = bt_find(bname); if (btype) { diff --git a/src/bind_dict.c b/src/bind_dict.c index 28bcc5d81..32d3c498d 100644 --- a/src/bind_dict.c +++ b/src/bind_dict.c @@ -47,7 +47,7 @@ static int tolua_dict_get(lua_State * L) lua_pushnil(L); break; case TINTEGER: - lua_pushnumber(L, (lua_Number)val.i); + lua_pushinteger(L, val.i); break; case TREAL: lua_pushnumber(L, (lua_Number)val.f); diff --git a/src/bind_faction.c b/src/bind_faction.c index df89f9d5a..585cdcf35 100644 --- a/src/bind_faction.c +++ b/src/bind_faction.c @@ -77,35 +77,35 @@ int tolua_faction_add_item(lua_State * L) result = i ? i->number : 0; } /* if (itype!=NULL) */ } - lua_pushnumber(L, result); + lua_pushinteger(L, result); return 1; } static int tolua_faction_get_maxheroes(lua_State * L) { faction *self = (faction *)tolua_tousertype(L, 1, 0); - tolua_pushnumber(L, (lua_Number)maxheroes(self)); + lua_pushinteger(L, maxheroes(self)); return 1; } static int tolua_faction_get_heroes(lua_State * L) { faction *self = (faction *)tolua_tousertype(L, 1, 0); - tolua_pushnumber(L, (lua_Number)countheroes(self)); + lua_pushinteger(L, countheroes(self)); return 1; } static int tolua_faction_get_score(lua_State * L) { faction *self = (faction *)tolua_tousertype(L, 1, 0); - tolua_pushnumber(L, (lua_Number)self->score); + lua_pushinteger(L, self->score); return 1; } static int tolua_faction_get_id(lua_State * L) { faction *self = (faction *)tolua_tousertype(L, 1, 0); - tolua_pushnumber(L, (lua_Number)self->no); + lua_pushinteger(L, self->no); return 1; } @@ -148,7 +148,7 @@ static int tolua_faction_set_magic(lua_State * L) static int tolua_faction_get_age(lua_State * L) { faction *self = (faction *)tolua_tousertype(L, 1, 0); - tolua_pushnumber(L, (lua_Number)self->age); + lua_pushinteger(L, self->age); return 1; } @@ -163,7 +163,7 @@ static int tolua_faction_set_age(lua_State * L) static int tolua_faction_get_flags(lua_State * L) { faction *self = (faction *)tolua_tousertype(L, 1, 0); - tolua_pushnumber(L, (lua_Number)self->flags); + lua_pushinteger(L, self->flags); return 1; } @@ -178,7 +178,7 @@ static int tolua_faction_set_flags(lua_State * L) static int tolua_faction_get_options(lua_State * L) { faction *self = (faction *)tolua_tousertype(L, 1, 0); - tolua_pushnumber(L, (lua_Number)self->options); + lua_pushinteger(L, self->options); return 1; } @@ -193,7 +193,7 @@ static int tolua_faction_set_options(lua_State * L) static int tolua_faction_get_lastturn(lua_State * L) { faction *self = (faction *)tolua_tousertype(L, 1, 0); - tolua_pushnumber(L, (lua_Number)self->lastorders); + lua_pushinteger(L, self->lastorders); return 1; } @@ -245,7 +245,7 @@ static int tolua_faction_get_policy(lua_State * L) } } - tolua_pushnumber(L, (lua_Number)result); + lua_pushinteger(L, result); return 1; } @@ -282,9 +282,9 @@ static int tolua_faction_normalize(lua_State * L) plane *pl = rplane(r); int nx = r->x, ny = r->y; pnormalize(&nx, &ny, pl); - adjust_coordinates(f, &nx, &ny, pl, r); - tolua_pushnumber(L, (lua_Number)nx); - tolua_pushnumber(L, (lua_Number)ny); + adjust_coordinates(f, &nx, &ny, pl); + lua_pushinteger(L, nx); + lua_pushinteger(L, ny); return 2; } return 0; @@ -297,7 +297,7 @@ static int tolua_faction_set_origin(lua_State * L) plane *pl = rplane(r); int id = pl ? pl->id : 0; - set_ursprung(f, id, r->x - plane_center_x(pl), r->y - plane_center_y(pl)); + faction_setorigin(f, id, r->x - plane_center_x(pl), r->y - plane_center_y(pl)); return 0; } @@ -319,8 +319,8 @@ static int tolua_faction_get_origin(lua_State * L) y = 0; } - tolua_pushnumber(L, (lua_Number)x); - tolua_pushnumber(L, (lua_Number)y); + lua_pushinteger(L, x); + lua_pushinteger(L, y); return 2; } @@ -344,14 +344,14 @@ static int tolua_faction_create(lua_State * L) const char *email = tolua_tostring(L, 1, 0); const char *racename = tolua_tostring(L, 2, 0); const char *lang = tolua_tostring(L, 3, 0); - struct locale *loc = get_locale(lang); + struct locale *loc = lang ? get_locale(lang) : default_locale; faction *f = NULL; - const struct race *frace = rc_find(racename); + const struct race *frace = rc_find(racename ? racename : "human"); if (frace != NULL) { f = addfaction(email, NULL, frace, loc, 0); } if (!f) { - log_error("faction.create(%s, %s, %s)\n", email, racename, lang); + log_error("faction.create(%s, %s, %s)\n", email, racename, locale_name(loc)); } tolua_pushusertype(L, f, TOLUA_CAST "faction"); return 1; @@ -443,7 +443,7 @@ static int tolua_faction_set_name(lua_State * L) static int tolua_faction_get_uid(lua_State * L) { faction *f = (faction *)tolua_tousertype(L, 1, 0); - tolua_pushnumber(L, f->subscription); + lua_pushinteger(L, f->subscription); return 1; } @@ -507,14 +507,6 @@ static int tolua_faction_tostring(lua_State * L) return 1; } -#ifdef TODO /* these usertypes are undefined */ -static int tolua_faction_get_spells(lua_State * L) -{ - faction *self = (faction *) tolua_tousertype(L, 1, 0); - return tolua_quicklist_push(L, "spellbook", "spellbook_entry", self->spellbook->spells); -} -#endif - void tolua_faction_open(lua_State * L) { /* register user types */ @@ -544,9 +536,6 @@ void tolua_faction_open(lua_State * L) &tolua_faction_set_info); tolua_variable(L, TOLUA_CAST "units", tolua_faction_get_units, NULL); tolua_variable(L, TOLUA_CAST "heroes", tolua_faction_get_heroes, NULL); -#ifdef TODO - tolua_variable(L, TOLUA_CAST "spells", tolua_faction_get_spells, 0); -#endif tolua_variable(L, TOLUA_CAST "maxheroes", tolua_faction_get_maxheroes, NULL); tolua_variable(L, TOLUA_CAST "password", tolua_faction_get_password, diff --git a/src/bind_gmtool.c b/src/bind_gmtool.c index 3a07cfc6b..3c07bb3b7 100644 --- a/src/bind_gmtool.c +++ b/src/bind_gmtool.c @@ -152,8 +152,8 @@ static int tolua_make_island(lua_State * L) int s = (int)tolua_tonumber(L, 3, 0); int n = (int)tolua_tonumber(L, 4, s / 3); - n = build_island_e3(x, y, n, s); - tolua_pushnumber(L, n); + n = build_island_e3(NULL, x, y, n, s); + lua_pushinteger(L, n); return 1; } @@ -166,8 +166,8 @@ static void lua_paint_info(struct window *wnd, const struct state *st) int nx = st->cursor.x, ny = st->cursor.y; pnormalize(&nx, &ny, st->cursor.pl); lua_rawgeti(L, LUA_REGISTRYINDEX, paint_handle); - tolua_pushnumber(L, nx); - tolua_pushnumber(L, ny); + lua_pushinteger(L, nx); + lua_pushinteger(L, ny); if (lua_pcall(L, 2, 1, 0) != 0) { const char *error = lua_tostring(L, -1); log_error("paint function failed: %s\n", error); diff --git a/src/bind_message.c b/src/bind_message.c index 24439804d..bbbd2bc0b 100644 --- a/src/bind_message.c +++ b/src/bind_message.c @@ -11,7 +11,9 @@ #include /* util includes */ +#include #include +#include /* lua includes */ #include @@ -212,7 +214,7 @@ static int tolua_msg_set_string(lua_State * L) const char *param = tolua_tostring(L, 2, 0); const char *value = tolua_tostring(L, 3, 0); int result = msg_set_string(lmsg, param, value); - tolua_pushnumber(L, (lua_Number)result); + lua_pushinteger(L, result); return 1; } @@ -222,7 +224,7 @@ static int tolua_msg_set_int(lua_State * L) const char *param = tolua_tostring(L, 2, 0); int value = (int)tolua_tonumber(L, 3, 0); int result = msg_set_int(lmsg, param, value); - tolua_pushnumber(L, (lua_Number)result); + lua_pushinteger(L, result); return 1; } @@ -232,7 +234,7 @@ static int tolua_msg_set_resource(lua_State * L) const char *param = tolua_tostring(L, 2, 0); const char *value = tolua_tostring(L, 3, 0); int result = msg_set_resource(lmsg, param, value); - tolua_pushnumber(L, (lua_Number)result); + lua_pushinteger(L, result); return 1; } @@ -242,7 +244,7 @@ static int tolua_msg_set_unit(lua_State * L) const char *param = tolua_tostring(L, 2, 0); unit *value = (unit *)tolua_tousertype(L, 3, 0); int result = msg_set_unit(lmsg, param, value); - tolua_pushnumber(L, (lua_Number)result); + lua_pushinteger(L, result); return 1; } @@ -252,7 +254,7 @@ static int tolua_msg_set_region(lua_State * L) const char *param = tolua_tostring(L, 2, 0); region *value = (region *)tolua_tousertype(L, 3, 0); int result = msg_set_region(lmsg, param, value); - tolua_pushnumber(L, (lua_Number)result); + lua_pushinteger(L, result); return 1; } @@ -268,7 +270,7 @@ static int tolua_msg_set(lua_State * L) else if (tolua_isusertype(L, 3, TOLUA_CAST "unit", 0, &err)) { return tolua_msg_set_unit(L); } - tolua_pushnumber(L, (lua_Number)-1); + lua_pushinteger(L, -1); return 1; } @@ -277,7 +279,7 @@ static int tolua_msg_send_region(lua_State * L) lua_message *lmsg = (lua_message *)tolua_tousertype(L, 1, 0); region *r = (region *)tolua_tousertype(L, 2, 0); int result = msg_send_region(lmsg, r); - tolua_pushnumber(L, (lua_Number)result); + lua_pushinteger(L, result); return 1; } @@ -291,7 +293,7 @@ static int tolua_msg_report_action(lua_State * L) lmsg->msg = msg_create(lmsg->mtype, lmsg->args); } result = report_action(r, u, lmsg->msg, flags); - tolua_pushnumber(L, (lua_Number)result); + lua_pushinteger(L, result); return 1; } @@ -301,12 +303,27 @@ static int tolua_msg_send_faction(lua_State * L) faction *f = (faction *)tolua_tousertype(L, 2, 0); if (f && lmsg) { int result = msg_send_faction(lmsg, f); - tolua_pushnumber(L, (lua_Number)result); + lua_pushinteger(L, result); return 1; } return 0; } +static int tolua_msg_render(lua_State * L) +{ + lua_message *lmsg = (lua_message *)tolua_tousertype(L, 1, 0); + const char * lname = tolua_tostring(L, 2, 0); + const struct locale * lang = lname ? get_locale(lname) : default_locale; + char name[64]; + + if (lmsg->msg == NULL) { + lmsg->msg = msg_create(lmsg->mtype, lmsg->args); + } + nr_render(lmsg->msg, lang, name, sizeof(name), NULL); + lua_pushstring(L, name); + return 1; +} + void tolua_message_open(lua_State * L) { /* register user types */ @@ -321,6 +338,7 @@ void tolua_message_open(lua_State * L) NULL); tolua_beginmodule(L, TOLUA_CAST "message"); { + tolua_function(L, TOLUA_CAST "render", tolua_msg_render); tolua_function(L, TOLUA_CAST "set", tolua_msg_set); tolua_function(L, TOLUA_CAST "set_unit", tolua_msg_set_unit); tolua_function(L, TOLUA_CAST "set_region", tolua_msg_set_region); diff --git a/src/bind_monsters.c b/src/bind_monsters.c index 8897da0d1..a106ec638 100644 --- a/src/bind_monsters.c +++ b/src/bind_monsters.c @@ -21,7 +21,7 @@ static int tolua_levitate_ship(lua_State * L) float power = (float)tolua_tonumber(L, 3, 0); int duration = (int)tolua_tonumber(L, 4, 0); int cno = levitate_ship(sh, mage, power, duration); - tolua_pushnumber(L, (lua_Number)cno); + lua_pushinteger(L, cno); return 1; } diff --git a/src/bind_region.c b/src/bind_region.c index 792f15ac0..f39baecda 100644 --- a/src/bind_region.c +++ b/src/bind_region.c @@ -62,7 +62,7 @@ int tolua_regionlist_next(lua_State * L) static int tolua_region_get_id(lua_State * L) { region *self = (region *)tolua_tousertype(L, 1, 0); - tolua_pushnumber(L, (lua_Number)self->uid); + lua_pushinteger(L, self->uid); return 1; } @@ -85,14 +85,14 @@ static int tolua_region_set_blocked(lua_State * L) static int tolua_region_get_x(lua_State * L) { region *self = (region *)tolua_tousertype(L, 1, 0); - tolua_pushnumber(L, (lua_Number)self->x); + lua_pushinteger(L, self->x); return 1; } static int tolua_region_get_y(lua_State * L) { region *self = (region *)tolua_tousertype(L, 1, 0); - tolua_pushnumber(L, (lua_Number)self->y); + lua_pushinteger(L, self->y); return 1; } @@ -199,7 +199,7 @@ static int tolua_region_set_name(lua_State * L) static int tolua_region_get_morale(lua_State * L) { region *r = (region *)tolua_tousertype(L, 1, 0); - tolua_pushnumber(L, region_get_morale(r)); + lua_pushinteger(L, region_get_morale(r)); return 1; } @@ -323,7 +323,7 @@ static int tolua_region_get_resourcelevel(lua_State * L) const rawmaterial *rm; for (rm = r->resources; rm; rm = rm->next) { if (rm->type->rtype == rtype) { - tolua_pushnumber(L, (lua_Number)rm->level); + lua_pushinteger(L, rm->level); return 1; } } @@ -355,7 +355,7 @@ static int tolua_region_get_resource(lua_State * L) const char *type; const resource_type *rtype; int result = 0; - const void * matches; + void * matches; critbit_tree * cb = special_resources(); r = (region *)tolua_tousertype(L, 1, 0); @@ -389,7 +389,7 @@ static int tolua_region_get_resource(lua_State * L) } } - tolua_pushnumber(L, (lua_Number)result); + lua_pushinteger(L, result); return 1; } @@ -399,7 +399,7 @@ static int tolua_region_set_resource(lua_State * L) const char *type = tolua_tostring(L, 2, 0); int result, value = (int)tolua_tonumber(L, 3, 0); critbit_tree * cb = special_resources(); - const void * matches; + void * matches; if (cb_find_prefix(cb, type, strlen(type) + 1, &matches, 1, 0)) { cb_get_kv(matches, &result, sizeof(result)); @@ -524,7 +524,7 @@ static int tolua_region_get_age(lua_State * L) region *self = (region *)tolua_tousertype(L, 1, 0); if (self) { - lua_pushnumber(L, self->age); + lua_pushinteger(L, self->age); return 1; } return 0; @@ -613,7 +613,7 @@ static int tolua_plane_set_name(lua_State * L) static int tolua_plane_get_id(lua_State * L) { plane *self = (plane *)tolua_tousertype(L, 1, 0); - tolua_pushnumber(L, (lua_Number)self->id); + lua_pushinteger(L, self->id); return 1; } @@ -623,8 +623,8 @@ static int tolua_plane_normalize(lua_State * L) int x = (int)tolua_tonumber(L, 2, 0); int y = (int)tolua_tonumber(L, 3, 0); pnormalize(&x, &y, self); - tolua_pushnumber(L, (lua_Number)x); - tolua_pushnumber(L, (lua_Number)y); + lua_pushinteger(L, x); + lua_pushinteger(L, y); return 2; } @@ -638,8 +638,8 @@ static int tolua_plane_tostring(lua_State * L) static int tolua_plane_get_size(lua_State * L) { plane *pl = (plane *)tolua_tousertype(L, 1, 0); - lua_pushnumber(L, plane_width(pl)); - lua_pushnumber(L, plane_height(pl)); + lua_pushinteger(L, plane_width(pl)); + lua_pushinteger(L, plane_height(pl)); return 2; } @@ -657,7 +657,7 @@ static int tolua_distance(lua_State * L) pnormalize(&x1, &y1, pl); pnormalize(&x2, &y2, pl); result = koor_distance(x1, y1, x2, y2); - lua_pushnumber(L, result); + lua_pushinteger(L, result); return 1; } diff --git a/src/bind_ship.c b/src/bind_ship.c index 7dd1b02f6..595be35dd 100644 --- a/src/bind_ship.c +++ b/src/bind_ship.c @@ -45,7 +45,7 @@ int tolua_shiplist_next(lua_State * L) static int tolua_ship_get_id(lua_State * L) { ship *self = (ship *)tolua_tousertype(L, 1, 0); - tolua_pushnumber(L, (lua_Number)self->no); + lua_pushinteger(L, self->no); return 1; } @@ -152,7 +152,7 @@ tolua_ship_tostring(lua_State * L) static int tolua_ship_get_flags(lua_State * L) { ship *self = (ship *)tolua_tousertype(L, 1, 0); - tolua_pushnumber(L, (lua_Number)self->flags); + lua_pushinteger(L, self->flags); return 1; } @@ -179,7 +179,7 @@ static int tolua_ship_get_coast(lua_State * L) { ship *self = (ship *)tolua_tousertype(L, 1, 0); if (self->coast) { - tolua_pushnumber(L, self->coast); + lua_pushinteger(L, self->coast); return 1; } return 0; diff --git a/src/bind_sqlite.c b/src/bind_sqlite.c index e2c0e69e3..e8c9b7565 100644 --- a/src/bind_sqlite.c +++ b/src/bind_sqlite.c @@ -44,7 +44,7 @@ static int tolua_db_execute(lua_State * L) int res = sqlite3_exec(db, sql, 0, 0, 0); - tolua_pushnumber(L, (LUA_NUMBER)res); + lua_pushinteger(L, res); return 1; } diff --git a/src/bind_storage.c b/src/bind_storage.c index d0fea8244..acdf1e046 100644 --- a/src/bind_storage.c +++ b/src/bind_storage.c @@ -77,7 +77,7 @@ static int tolua_storage_read_float(lua_State * L) gamedata *data = (gamedata *)tolua_tousertype(L, 1, 0); float num; READ_FLT(data->store, &num); - tolua_pushnumber(L, (lua_Number)num); + lua_pushnumber(L, num); return 1; } @@ -86,7 +86,7 @@ static int tolua_storage_read_int(lua_State * L) gamedata *data = (gamedata *)tolua_tousertype(L, 1, 0); int num; READ_INT(data->store, &num); - tolua_pushnumber(L, (lua_Number)num); + lua_pushinteger(L, num); return 1; } diff --git a/src/bind_unit.c b/src/bind_unit.c index e18a81d8a..59f2ad13c 100755 --- a/src/bind_unit.c +++ b/src/bind_unit.c @@ -14,9 +14,6 @@ without prior permission by the authors of Eressea. #include "bind_unit.h" #include "bind_dict.h" -#ifdef BSON_ATTRIB -# include "bind_attrib.h" -#endif #include "alchemy.h" #include "bindings.h" #include "move.h" @@ -64,23 +61,6 @@ static int tolua_unit_get_objects(lua_State * L) return 1; } -#ifdef BSON_ATTRIB -static int tolua_unit_get_attribs(lua_State * L) -{ - unit *self = (unit *) tolua_tousertype(L, 1, 0); - attrib **attrib_ptr = (attrib **) lua_newuserdata(L, sizeof(attrib *)); - attrib *a = tolua_get_lua_ext(self->attribs); - - luaL_getmetatable(L, "attrib"); - lua_setmetatable(L, -2); - - *attrib_ptr = a; - - lua_pushcclosure(L, tolua_attriblist_next, 1); - return 1; -} -#endif - int tolua_unitlist_nextf(lua_State * L) { unit **unit_ptr = (unit **)lua_touserdata(L, lua_upvalueindex(1)); @@ -160,14 +140,14 @@ static int tolua_unit_set_group(lua_State * L) { unit *self = (unit *)tolua_tousertype(L, 1, 0); int result = join_group(self, tolua_tostring(L, 2, 0)); - tolua_pushnumber(L, result); + lua_pushinteger(L, result); return 1; } static int tolua_unit_get_name(lua_State * L) { unit *self = (unit *)tolua_tousertype(L, 1, 0); - tolua_pushstring(L, self->name); + tolua_pushstring(L, unit_getname(self)); return 1; } @@ -262,6 +242,24 @@ static int tolua_unit_set_flags(lua_State * L) return 0; } +static int tolua_unit_get_guard(lua_State * L) +{ + unit *self = (unit *)tolua_tousertype(L, 1, 0); + if (is_guard(self, GUARD_ALL)) { + lua_pushinteger(L, getguard(self)); + return 1; + } + return 0; +} + +static int tolua_unit_set_guard(lua_State * L) +{ + unit *self = (unit *)tolua_tousertype(L, 1, 0); + unsigned int flags = (unsigned int)tolua_tonumber(L, 2, 0); + setguard(self, flags); + return 0; +} + static const char *unit_getmagic(const unit * u) { sc_mage *mage = get_mage(u); @@ -542,7 +540,7 @@ static int tolua_unit_addspell(lua_State * L) spell *sp = find_spell(str); if (!sp) { - log_error("spell %s could not be found\n", str); + log_warning("spell %s could not be found\n", str); return EINVAL; } else { @@ -740,23 +738,22 @@ static int tolua_unit_get_items(lua_State * L) return 1; } -#ifdef TODO /* spellbooks */ static int tolua_unit_get_spells(lua_State * L) { unit *self = (unit *) tolua_tousertype(L, 1, 0); - sc_mage *mage = get_mage(self); + sc_mage *mage = self ? get_mage(self) : 0; + spellbook *sb = mage ? mage->spellbook : 0; quicklist *slist = 0; - - if (mage) { - quicklist **slist_ptr = get_spelllist(mage, self->faction); + if (sb) { + quicklist **slist_ptr = &sb->spells; if (slist_ptr) { slist = *slist_ptr; } } - - return tolua_quicklist_push(L, "spell_list", "spell", slist); + return tolua_quicklist_push(L, "spellbook", "spell_entry", slist); } +#ifdef TODO /* spellbooks */ static void unit_removespell(unit * u, spell * sp) { quicklist **isptr; @@ -984,6 +981,8 @@ void tolua_unit_open(lua_State * L) /* key-attributes for named flags: */ tolua_function(L, TOLUA_CAST "set_flag", &tolua_unit_set_flag); tolua_function(L, TOLUA_CAST "get_flag", &tolua_unit_get_flag); + tolua_variable(L, TOLUA_CAST "guard", &tolua_unit_get_guard, + &tolua_unit_set_guard); tolua_variable(L, TOLUA_CAST "flags", &tolua_unit_get_flags, &tolua_unit_set_flags); tolua_variable(L, TOLUA_CAST "age", &tolua_unit_get_age, @@ -1014,8 +1013,8 @@ void tolua_unit_open(lua_State * L) tolua_function(L, TOLUA_CAST "add_spell", &tolua_unit_addspell); #ifdef TODO /* spellbooks */ tolua_function(L, TOLUA_CAST "remove_spell", &tolua_unit_removespell); - tolua_variable(L, TOLUA_CAST "spells", &tolua_unit_get_spells, 0); #endif + tolua_variable(L, TOLUA_CAST "spells", &tolua_unit_get_spells, 0); tolua_function(L, TOLUA_CAST "cast_spell", &tolua_unit_castspell); tolua_variable(L, TOLUA_CAST "magic", &tolua_unit_get_magic, @@ -1035,9 +1034,6 @@ void tolua_unit_open(lua_State * L) tolua_variable(L, TOLUA_CAST "hp_max", &tolua_unit_get_hpmax, 0); tolua_variable(L, TOLUA_CAST "objects", &tolua_unit_get_objects, 0); -#ifdef BSON_ATTRIB - tolua_variable(L, TOLUA_CAST "attribs", &tolua_unit_get_attribs, 0); -#endif } tolua_endmodule(L); } diff --git a/src/bindings.c b/src/bindings.c index 0385506cf..3e842ba92 100755 --- a/src/bindings.c +++ b/src/bindings.c @@ -47,6 +47,7 @@ without prior permission by the authors of Eressea. #include #include #include +#include #include "creport.h" #include "economy.h" @@ -93,7 +94,7 @@ TOLUA_PKG(game); int log_lua_error(lua_State * L) { const char *error = lua_tostring(L, -1); - log_error("LUA call failed.\n%s\n", error); + log_fatal("LUA call failed.\n%s\n", error); lua_pop(L, 1); return 1; } @@ -117,12 +118,12 @@ static int tolua_quicklist_iter(lua_State * L) quicklist **qlp = (quicklist **)lua_touserdata(L, lua_upvalueindex(1)); quicklist *ql = *qlp; if (ql != NULL) { - int index = lua_tointeger(L, lua_upvalueindex(2)); + int index = (int)lua_tointeger(L, lua_upvalueindex(2)); const char *type = lua_tostring(L, lua_upvalueindex(3)); void *data = ql_get(ql, index); tolua_pushusertype(L, data, TOLUA_CAST type); ql_advance(qlp, &index, 1); - tolua_pushnumber(L, index); + lua_pushinteger(L, index); lua_replace(L, lua_upvalueindex(2)); return 1; } @@ -138,7 +139,7 @@ int tolua_quicklist_push(struct lua_State *L, const char *list_type, *qlist_ptr = list; luaL_getmetatable(L, list_type); lua_setmetatable(L, -2); - lua_pushnumber(L, 0); + lua_pushinteger(L, 0); lua_pushstring(L, elem_type); lua_pushcclosure(L, tolua_quicklist_iter, 3); /* OBS: this closure has multiple upvalues (list, index, type_name) */ } @@ -218,7 +219,7 @@ static int tolua_setkey(lua_State * L) static int tolua_rng_int(lua_State * L) { - lua_pushnumber(L, (lua_Number)rng_int()); + lua_pushinteger(L, rng_int()); return 1; } @@ -226,7 +227,7 @@ static int tolua_read_orders(lua_State * L) { const char *filename = tolua_tostring(L, 1, 0); int result = readorders(filename); - lua_pushnumber(L, (lua_Number)result); + lua_pushinteger(L, result); return 1; } @@ -281,14 +282,14 @@ static int tolua_set_turn(lua_State * L) static int tolua_get_turn(lua_State * L) { - tolua_pushnumber(L, (lua_Number)turn); + lua_pushinteger(L, turn); return 1; } static int tolua_atoi36(lua_State * L) { const char *s = tolua_tostring(L, 1, 0); - tolua_pushnumber(L, (lua_Number)atoi36(s)); + lua_pushinteger(L, atoi36(s)); return 1; } @@ -302,7 +303,7 @@ static int tolua_itoa36(lua_State * L) static int tolua_dice_rand(lua_State * L) { const char *s = tolua_tostring(L, 1, 0); - tolua_pushnumber(L, dice_rand(s)); + lua_pushinteger(L, dice_rand(s)); return 1; } @@ -319,7 +320,7 @@ static int tolua_addequipment(lua_State * L) result = 0; } } - lua_pushnumber(L, (lua_Number)result); + lua_pushinteger(L, result); return 1; } @@ -425,7 +426,7 @@ static int tolua_get_nmrs(lua_State * L) } result = nmrs[n]; } - tolua_pushnumber(L, (lua_Number)result); + lua_pushinteger(L, result); return 1; } @@ -433,7 +434,9 @@ static int tolua_equipunit(lua_State * L) { unit *u = (unit *)tolua_tousertype(L, 1, 0); const char *eqname = tolua_tostring(L, 2, 0); - equip_unit(u, get_equipment(eqname)); + int mask = (int)tolua_tonumber(L, 3, EQUIP_ALL); + assert(mask > 0); + equip_unit_mask(u, get_equipment(eqname), mask); return 0; } @@ -450,7 +453,7 @@ static int tolua_equipment_setitem(lua_State * L) result = 0; } } - tolua_pushnumber(L, (lua_Number)result); + lua_pushinteger(L, result); return 1; } @@ -464,7 +467,7 @@ static int tolua_spawn_braineaters(lua_State * L) static int tolua_init_reports(lua_State * L) { int result = init_reports(); - tolua_pushnumber(L, (lua_Number)result); + lua_pushinteger(L, result); return 1; } @@ -474,7 +477,7 @@ static int tolua_write_report(lua_State * L) if (f) { time_t ltime = time(0); int result = write_reports(f, ltime); - tolua_pushnumber(L, (lua_Number)result); + lua_pushinteger(L, result); } else { tolua_pushstring(L, "function expects a faction, got nil"); @@ -487,7 +490,7 @@ static int tolua_write_reports(lua_State * L) int result; init_reports(); result = reports(); - tolua_pushnumber(L, (lua_Number)result); + lua_pushinteger(L, result); return 1; } @@ -533,7 +536,7 @@ static int tolua_process_orders(lua_State * L) static int tolua_write_passwords(lua_State * L) { int result = writepasswd(); - lua_pushnumber(L, (lua_Number)result); + lua_pushinteger(L, result); return 0; } @@ -567,7 +570,7 @@ static int tolua_write_map(lua_State * L) static int tolua_read_turn(lua_State * L) { int cturn = current_turn(); - tolua_pushnumber(L, (lua_Number)cturn); + lua_pushinteger(L, cturn); return 1; } @@ -660,7 +663,7 @@ static int tolua_get_alliance_factions(lua_State * L) static int tolua_get_alliance_id(lua_State * L) { alliance *self = (alliance *)tolua_tousertype(L, 1, 0); - tolua_pushnumber(L, (lua_Number)self->id); + lua_pushinteger(L, self->id); return 1; } @@ -981,16 +984,29 @@ static int tolua_get_spell_school(lua_State * L) static int tolua_get_spell_level(lua_State * L) { spell *self = (spell *) tolua_tousertype(L, 1, 0); - lua_pushnumber(L, self->level); + lua_pushinteger(L, self->level); return 1; } #endif static int tolua_get_spell_name(lua_State * L) { - const struct locale *lang = default_locale; spell *self = (spell *)tolua_tousertype(L, 1, 0); - lua_pushstring(L, spell_name(self, lang)); + lua_pushstring(L, self->sname); + return 1; +} + +static int tolua_get_spell_entry_name(lua_State * L) +{ + spellbook_entry *self = (spellbook_entry*)tolua_tousertype(L, 1, 0); + lua_pushstring(L, self->sp->sname); + return 1; +} + +static int tolua_get_spell_entry_level(lua_State * L) +{ + spellbook_entry *self = (spellbook_entry*)tolua_tousertype(L, 1, 0); + lua_pushinteger(L, self->level); return 1; } @@ -1055,7 +1071,7 @@ static void parse_inifile(lua_State * L, dictionary * d, const char *section) tolua_pushstring(L, str_value); } else { - tolua_pushnumber(L, num_value); + lua_pushnumber(L, num_value); } lua_rawset(L, -3); } @@ -1085,6 +1101,8 @@ int tolua_bindings_open(lua_State * L) tolua_bind_open(L); /* register user types */ + tolua_usertype(L, TOLUA_CAST "spellbook"); + tolua_usertype(L, TOLUA_CAST "spell_entry"); tolua_usertype(L, TOLUA_CAST "spell"); tolua_usertype(L, TOLUA_CAST "spell_list"); tolua_usertype(L, TOLUA_CAST "order"); @@ -1112,12 +1130,16 @@ int tolua_bindings_open(lua_State * L) { tolua_function(L, TOLUA_CAST "__tostring", tolua_get_spell_name); tolua_variable(L, TOLUA_CAST "name", tolua_get_spell_name, 0); -#ifdef TODO - tolua_variable(L, TOLUA_CAST "school", tolua_get_spell_school, 0); - tolua_variable(L, TOLUA_CAST "level", tolua_get_spell_level, 0); -#endif tolua_variable(L, TOLUA_CAST "text", tolua_get_spell_text, 0); } tolua_endmodule(L); + tolua_cclass(L, TOLUA_CAST "spell_entry", TOLUA_CAST "spell_entry", TOLUA_CAST "", + NULL); + tolua_beginmodule(L, TOLUA_CAST "spell_entry"); + { + tolua_function(L, TOLUA_CAST "__tostring", tolua_get_spell_entry_name); + tolua_variable(L, TOLUA_CAST "name", tolua_get_spell_entry_name, 0); + tolua_variable(L, TOLUA_CAST "level", tolua_get_spell_entry_level, 0); + } tolua_endmodule(L); tolua_module(L, TOLUA_CAST "report", 1); tolua_beginmodule(L, TOLUA_CAST "report"); { diff --git a/src/buildno.h b/src/buildno.h index 69c61645e..ba737a69f 100644 --- a/src/buildno.h +++ b/src/buildno.h @@ -1,3 +1,3 @@ #define VERSION_MAJOR 3 -#define VERSION_MINOR 4 +#define VERSION_MINOR 6 #define VERSION_BUILD 1 diff --git a/src/creport.c b/src/creport.c index fc823284f..fefd7934e 100644 --- a/src/creport.c +++ b/src/creport.c @@ -1,4 +1,4 @@ -/* +/* +-------------------+ Enno Rehling | Eressea PBEM host | Christian Schlittchen | (c) 1998 - 2008 | Katja Zedel @@ -62,7 +62,7 @@ without prior permission by the authors of Eressea. #include #include #include -#include +#include #include #include #include @@ -184,9 +184,9 @@ cr_output_curses(FILE * F, const faction * viewer, const void *obj, objtype_t ty region *r; /* Die Sichtbarkeit eines Zaubers und die Zaubermeldung sind bei - * Gebuden und Schiffen je nach, ob man Besitzer ist, verschieden. + * Gebäuden und Schiffen je nach, ob man Besitzer ist, verschieden. * Bei Einheiten sieht man Wirkungen auf eigene Einheiten immer. - * Spezialflle (besonderes Talent, verursachender Magier usw. werde + * Spezialfälle (besonderes Talent, verursachender Magier usw. werde * bei jedem curse gesondert behandelt. */ if (typ == TYP_SHIP) { ship *sh = (ship *)obj; @@ -264,6 +264,7 @@ cr_output_curses(FILE * F, const faction * viewer, const void *obj, objtype_t ty fprintf(F, "\"%s\"\n", buf); msg_release(msg); } + a = a->next; } else if (a->type == &at_effect && self) { effect_data *data = (effect_data *)a->data.v; @@ -276,8 +277,11 @@ cr_output_curses(FILE * F, const faction * viewer, const void *obj, objtype_t ty fprintf(F, "\"%d %s\"\n", data->value, translate(key, LOC(default_locale, key))); } + a = a->next; + } + else { + a = a->nexttype; } - a = a->next; } } @@ -317,7 +321,7 @@ static int cr_region(variant var, char *buffer, const void *userdata) plane *pl = rplane(r); int nx = r->x, ny = r->y; pnormalize(&nx, &ny, pl); - adjust_coordinates(report, &nx, &ny, pl, r); + adjust_coordinates(report, &nx, &ny, pl); sprintf(buffer, "%d %d %d", nx, ny, plane_id(pl)); return 0; } @@ -435,7 +439,7 @@ static int cr_regions(variant var, char *buffer, const void *userdata) int nx = r->x, ny = r->y; pnormalize(&nx, &ny, pl); - adjust_coordinates(f, &nx, &ny, pl, r); + adjust_coordinates(f, &nx, &ny, pl); wp += sprintf(wp, "\"%d %d %d", nx, ny, z); for (i = 1; i != rdata->nregions; ++i) { r = rdata->regions[i]; @@ -743,8 +747,11 @@ static void cr_output_unit(FILE * F, const region * r, const faction * f, static const curse_type *itemcloak_ct = 0; static bool init = false; item result[MAX_INVENTORY]; + const faction *sf; + const char *prefix; - if (fval(u_race(u), RCF_INVISIBLE)) + assert(u && u->number); + if (u != NULL || fval(u_race(u), RCF_INVISIBLE)) return; if (!init) { @@ -752,256 +759,254 @@ static void cr_output_unit(FILE * F, const region * r, const faction * f, itemcloak_ct = ct_find("itemcloak"); } if (itemcloak_ct != NULL) { - itemcloak = curse_active(get_curse(u->attribs, itemcloak_ct)); + curse * cu = get_curse(u->attribs, itemcloak_ct); + itemcloak = cu && curse_active(cu); } - assert(u && u->number); - fprintf(F, "EINHEIT %d\n", u->no); - fprintf(F, "\"%s\";Name\n", u->name); + fprintf(F, "\"%s\";Name\n", unit_getname(u)); str = u_description(u, f->locale); if (str) { fprintf(F, "\"%s\";Beschr\n", str); } - { - /* print faction information */ - const faction *sf = visible_faction(f, u); - const char *prefix = raceprefix(u); - if (u->faction == f || omniscient(f)) { - const attrib *a_otherfaction = a_find(u->attribs, &at_otherfaction); - const faction *otherfaction = - a_otherfaction ? get_otherfaction(a_otherfaction) : NULL; - /* my own faction, full info */ - const attrib *a = NULL; - unit *mage; + /* print faction information */ + sf = visible_faction(f, u); + prefix = raceprefix(u); + if (u->faction == f || omniscient(f)) { + const attrib *a_otherfaction = a_find(u->attribs, &at_otherfaction); + const faction *otherfaction = + a_otherfaction ? get_otherfaction(a_otherfaction) : NULL; + /* my own faction, full info */ + const attrib *a = NULL; + unit *mage; - if (fval(u, UFL_GROUP)) - a = a_find(u->attribs, &at_group); - if (a != NULL) { - const group *g = (const group *)a->data.v; - fprintf(F, "%d;gruppe\n", g->gid); - } - fprintf(F, "%d;Partei\n", u->faction->no); - if (sf != u->faction) - fprintf(F, "%d;Verkleidung\n", sf->no); - if (fval(u, UFL_ANON_FACTION)) - fprintf(F, "%d;Parteitarnung\n", i2b(fval(u, UFL_ANON_FACTION))); - if (otherfaction) { - if (otherfaction != u->faction) { - fprintf(F, "%d;Anderepartei\n", otherfaction->no); - } - } - mage = get_familiar_mage(u); - if (mage) { - fprintf(F, "%u;familiarmage\n", mage->no); - } - } - else { - if (fval(u, UFL_ANON_FACTION)) { - /* faction info is hidden */ - fprintf(F, "%d;Parteitarnung\n", i2b(fval(u, UFL_ANON_FACTION))); - } - else { - const attrib *a_otherfaction = a_find(u->attribs, &at_otherfaction); - const faction *otherfaction = - a_otherfaction ? get_otherfaction(a_otherfaction) : NULL; - /* other unit. show visible faction, not u->faction */ - fprintf(F, "%d;Partei\n", sf->no); - if (sf == f) { - fprintf(F, "1;Verraeter\n"); - } - if (a_otherfaction) { - if (otherfaction != u->faction) { - if (alliedunit(u, f, HELP_FSTEALTH)) { - fprintf(F, "%d;Anderepartei\n", otherfaction->no); - } - } - } - } - } - if (prefix) { - prefix = mkname("prefix", prefix); - fprintf(F, "\"%s\";typprefix\n", translate(prefix, LOC(f->locale, - prefix))); - } - } - if (u->faction != f && a_fshidden - && a_fshidden->data.ca[0] == 1 && effskill(u, SK_STEALTH) >= 6) { - fprintf(F, "-1;Anzahl\n"); - } - else { - fprintf(F, "%d;Anzahl\n", u->number); - } + if (fval(u, UFL_GROUP)) + a = a_find(u->attribs, &at_group); + if (a != NULL) { + const group *g = (const group *)a->data.v; + fprintf(F, "%d;gruppe\n", g->gid); + } + fprintf(F, "%d;Partei\n", u->faction->no); + if (sf != u->faction) + fprintf(F, "%d;Verkleidung\n", sf->no); + if (fval(u, UFL_ANON_FACTION)) + fprintf(F, "%d;Parteitarnung\n", i2b(fval(u, UFL_ANON_FACTION))); + if (otherfaction) { + if (otherfaction != u->faction) { + fprintf(F, "%d;Anderepartei\n", otherfaction->no); + } + } + mage = get_familiar_mage(u); + if (mage) { + fprintf(F, "%u;familiarmage\n", mage->no); + } + } + else { + if (fval(u, UFL_ANON_FACTION)) { + /* faction info is hidden */ + fprintf(F, "%d;Parteitarnung\n", i2b(fval(u, UFL_ANON_FACTION))); + } + else { + const attrib *a_otherfaction = a_find(u->attribs, &at_otherfaction); + const faction *otherfaction = + a_otherfaction ? get_otherfaction(a_otherfaction) : NULL; + /* other unit. show visible faction, not u->faction */ + fprintf(F, "%d;Partei\n", sf->no); + if (sf == f) { + fprintf(F, "1;Verraeter\n"); + } + if (a_otherfaction) { + if (otherfaction != u->faction) { + if (alliedunit(u, f, HELP_FSTEALTH)) { + fprintf(F, "%d;Anderepartei\n", otherfaction->no); + } + } + } + } + } + if (prefix) { + prefix = mkname("prefix", prefix); + fprintf(F, "\"%s\";typprefix\n", translate(prefix, LOC(f->locale, + prefix))); + } + if (u->faction != f && a_fshidden + && a_fshidden->data.ca[0] == 1 && effskill(u, SK_STEALTH) >= 6) { + fprintf(F, "-1;Anzahl\n"); + } + else { + fprintf(F, "%d;Anzahl\n", u->number); + } - pzTmp = get_racename(u->attribs); - if (pzTmp) { - fprintf(F, "\"%s\";Typ\n", pzTmp); - if (u->faction == f && fval(u_race(u), RCF_SHAPESHIFTANY)) { - const char *zRace = rc_name_s(u_race(u), NAME_PLURAL); - fprintf(F, "\"%s\";wahrerTyp\n", - translate(zRace, LOC(f->locale, zRace))); - } - } - else { - const race *irace = u_irace(u); - const char *zRace = rc_name_s(irace, NAME_PLURAL); - fprintf(F, "\"%s\";Typ\n", - translate(zRace, LOC(f->locale, zRace))); - if (u->faction == f && irace != u_race(u)) { - assert(skill_enabled(SK_STEALTH) - || !"we're resetting this on load, so.. ircase should never be used"); - zRace = rc_name_s(u_race(u), NAME_PLURAL); - fprintf(F, "\"%s\";wahrerTyp\n", - translate(zRace, LOC(f->locale, zRace))); - } - } + pzTmp = get_racename(u->attribs); + if (pzTmp) { + fprintf(F, "\"%s\";Typ\n", pzTmp); + if (u->faction == f && fval(u_race(u), RCF_SHAPESHIFTANY)) { + const char *zRace = rc_name_s(u_race(u), NAME_PLURAL); + fprintf(F, "\"%s\";wahrerTyp\n", + translate(zRace, LOC(f->locale, zRace))); + } + } + else { + const race *irace = u_irace(u); + const char *zRace = rc_name_s(irace, NAME_PLURAL); + fprintf(F, "\"%s\";Typ\n", + translate(zRace, LOC(f->locale, zRace))); + if (u->faction == f && irace != u_race(u)) { + assert(skill_enabled(SK_STEALTH) + || !"we're resetting this on load, so.. ircase should never be used"); + zRace = rc_name_s(u_race(u), NAME_PLURAL); + fprintf(F, "\"%s\";wahrerTyp\n", + translate(zRace, LOC(f->locale, zRace))); + } + } - if (u->building) { - assert(u->building->region); - fprintf(F, "%d;Burg\n", u->building->no); - } - if (u->ship) { - assert(u->ship->region); - fprintf(F, "%d;Schiff\n", u->ship->no); - } - if (is_guard(u, GUARD_ALL) != 0) { - fprintf(F, "%d;bewacht\n", 1); - } - if ((b = usiege(u)) != NULL) { - fprintf(F, "%d;belagert\n", b->no); - } - /* additional information for own units */ - if (u->faction == f || omniscient(f)) { - order *ord; - const char *xc; - const char *c; - int i; - sc_mage *mage; + if (u->building) { + assert(u->building->region); + fprintf(F, "%d;Burg\n", u->building->no); + } + if (u->ship) { + assert(u->ship->region); + fprintf(F, "%d;Schiff\n", u->ship->no); + } + if (is_guard(u, GUARD_ALL) != 0) { + fprintf(F, "%d;bewacht\n", 1); + } + if ((b = usiege(u)) != NULL) { + fprintf(F, "%d;belagert\n", b->no); + } + /* additional information for own units */ + if (u->faction == f || omniscient(f)) { + order *ord; + const char *xc; + const char *c; + int i; + sc_mage *mage; - i = ualias(u); - if (i > 0) - fprintf(F, "%d;temp\n", i); - else if (i < 0) - fprintf(F, "%d;alias\n", -i); - i = get_money(u); - fprintf(F, "%d;Kampfstatus\n", u->status); - fprintf(F, "%d;weight\n", weight(u)); - if (fval(u, UFL_NOAID)) { - fputs("1;unaided\n", F); - } - if (fval(u, UFL_STEALTH)) { - i = u_geteffstealth(u); - if (i >= 0) { - fprintf(F, "%d;Tarnung\n", i); - } - } - xc = uprivate(u); - if (xc) { - fprintf(F, "\"%s\";privat\n", xc); - } - c = hp_status(u); - if (c && *c && (u->faction == f || omniscient(f))) { - fprintf(F, "\"%s\";hp\n", translate(c, - LOC(u->faction->locale, c))); - } - if (fval(u, UFL_HERO)) { - fputs("1;hero\n", F); - } + i = ualias(u); + if (i > 0) + fprintf(F, "%d;temp\n", i); + else if (i < 0) + fprintf(F, "%d;alias\n", -i); + i = get_money(u); + fprintf(F, "%d;Kampfstatus\n", u->status); + fprintf(F, "%d;weight\n", weight(u)); + if (fval(u, UFL_NOAID)) { + fputs("1;unaided\n", F); + } + if (fval(u, UFL_STEALTH)) { + i = u_geteffstealth(u); + if (i >= 0) { + fprintf(F, "%d;Tarnung\n", i); + } + } + xc = uprivate(u); + if (xc) { + fprintf(F, "\"%s\";privat\n", xc); + } + c = hp_status(u); + if (c && *c && (u->faction == f || omniscient(f))) { + fprintf(F, "\"%s\";hp\n", translate(c, + LOC(u->faction->locale, c))); + } + if (fval(u, UFL_HERO)) { + fputs("1;hero\n", F); + } - if (fval(u, UFL_HUNGER) && (u->faction == f)) { - fputs("1;hunger\n", F); - } - if (is_mage(u)) { - fprintf(F, "%d;Aura\n", get_spellpoints(u)); - fprintf(F, "%d;Auramax\n", max_spellpoints(u->region, u)); - } - /* default commands */ - fprintf(F, "COMMANDS\n"); - for (ord = u->old_orders; ord; ord = ord->next) { - /* this new order will replace the old defaults */ - if (is_persistent(ord)) { - fwriteorder(F, ord, f->locale, true); - fputc('\n', F); - } - } - for (ord = u->orders; ord; ord = ord->next) { - if (u->old_orders && is_repeated(ord)) - continue; /* unit has defaults */ - if (is_persistent(ord)) { - fwriteorder(F, ord, f->locale, true); - fputc('\n', F); - } - } + if (fval(u, UFL_HUNGER) && (u->faction == f)) { + fputs("1;hunger\n", F); + } + if (is_mage(u)) { + fprintf(F, "%d;Aura\n", get_spellpoints(u)); + fprintf(F, "%d;Auramax\n", max_spellpoints(u->region, u)); + } + /* default commands */ + fprintf(F, "COMMANDS\n"); + for (ord = u->old_orders; ord; ord = ord->next) { + /* this new order will replace the old defaults */ + if (is_persistent(ord)) { + fwriteorder(F, ord, f->locale, true); + fputc('\n', F); + } + } + for (ord = u->orders; ord; ord = ord->next) { + keyword_t kwd = getkeyword(ord); + if (u->old_orders && is_repeated(kwd)) + continue; /* unit has defaults */ + if (is_persistent(ord)) { + fwriteorder(F, ord, f->locale, true); + fputc('\n', F); + } + } - /* talents */ - pr = 0; - for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) { - if (sv->level > 0) { - skill_t sk = sv->id; - int esk = eff_skill(u, sk, r); - if (!pr) { - pr = 1; - fprintf(F, "TALENTE\n"); - } - fprintf(F, "%d %d;%s\n", u->number * level_days(sv->level), esk, - translate(mkname("skill", skillnames[sk]), skillname(sk, - f->locale))); - } - } + /* talents */ + pr = 0; + for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) { + if (sv->level > 0) { + skill_t sk = sv->id; + int esk = eff_skill(u, sk, r); + if (!pr) { + pr = 1; + fprintf(F, "TALENTE\n"); + } + fprintf(F, "%d %d;%s\n", u->number * level_days(sv->level), esk, + translate(mkname("skill", skillnames[sk]), skillname(sk, + f->locale))); + } + } - /* spells that this unit can cast */ - mage = get_mage(u); - if (mage) { - int i, maxlevel = effskill(u, SK_MAGIC); - cr_output_spells(F, u, maxlevel); + /* spells that this unit can cast */ + mage = get_mage(u); + if (mage) { + int i, maxlevel = effskill(u, SK_MAGIC); + cr_output_spells(F, u, maxlevel); - for (i = 0; i != MAXCOMBATSPELLS; ++i) { - const spell *sp = mage->combatspells[i].sp; - if (sp) { - const char *name = - translate(mkname("spell", sp->sname), spell_name(sp, - f->locale)); - fprintf(F, "KAMPFZAUBER %d\n", i); - fprintf(F, "\"%s\";name\n", name); - fprintf(F, "%d;level\n", mage->combatspells[i].level); - } - } - } - } - /* items */ - pr = 0; - if (f == u->faction || omniscient(f)) { - show = u->items; - } - else if (!itemcloak && mode >= see_unit && !(a_fshidden - && a_fshidden->data.ca[1] == 1 && effskill(u, SK_STEALTH) >= 3)) { - int n = report_items(u->items, result, MAX_INVENTORY, u, f); - assert(n >= 0); - if (n > 0) - show = result; - else - show = NULL; - } - else { - show = NULL; - } - lasttype = NULL; - for (itm = show; itm; itm = itm->next) { - const char *ic; - int in; - assert(itm->type != lasttype - || !"error: list contains two objects of the same item"); - report_item(u, itm, f, NULL, &ic, &in, true); - if (in == 0) - continue; - if (!pr) { - pr = 1; - fputs("GEGENSTAENDE\n", F); - } - fprintf(F, "%d;%s\n", in, translate(ic, LOC(f->locale, ic))); - } + for (i = 0; i != MAXCOMBATSPELLS; ++i) { + const spell *sp = mage->combatspells[i].sp; + if (sp) { + const char *name = + translate(mkname("spell", sp->sname), spell_name(sp, + f->locale)); + fprintf(F, "KAMPFZAUBER %d\n", i); + fprintf(F, "\"%s\";name\n", name); + fprintf(F, "%d;level\n", mage->combatspells[i].level); + } + } + } + } + /* items */ + pr = 0; + if (f == u->faction || omniscient(f)) { + show = u->items; + } + else if (!itemcloak && mode >= see_unit && !(a_fshidden + && a_fshidden->data.ca[1] == 1 && effskill(u, SK_STEALTH) >= 3)) { + int n = report_items(u->items, result, MAX_INVENTORY, u, f); + assert(n >= 0); + if (n > 0) + show = result; + else + show = NULL; + } + else { + show = NULL; + } + lasttype = NULL; + for (itm = show; itm; itm = itm->next) { + const char *ic; + int in; + assert(itm->type != lasttype + || !"error: list contains two objects of the same item"); + report_item(u, itm, f, NULL, &ic, &in, true); + if (in == 0) + continue; + if (!pr) { + pr = 1; + fputs("GEGENSTAENDE\n", F); + } + fprintf(F, "%d;%s\n", in, translate(ic, LOC(f->locale, ic))); + } - cr_output_curses(F, f, u, TYP_UNIT); + cr_output_curses(F, f, u, TYP_UNIT); } /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ @@ -1033,18 +1038,6 @@ static void show_alliances_cr(FILE * F, const faction * f) } } -/* prints all visible spells in a region */ -static void show_active_spells(const region * r) -{ - char fogwall[MAXDIRECTIONS]; -#ifdef TODO /* alte Regionszauberanzeigen umstellen */ - unit *u; - int env = 0; -#endif - memset(fogwall, 0, sizeof(char) * MAXDIRECTIONS); - -} - /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ /* this is a copy of laws.c->find_address output changed. */ @@ -1222,7 +1215,7 @@ cr_output_resources(FILE * F, report_context * ctx, seen_region * sr) } static void -cr_region_header(FILE * F, int plid, int nx, int ny, unsigned int uid) +cr_region_header(FILE * F, int plid, int nx, int ny, int uid) { if (plid == 0) { fprintf(F, "REGION %d %d\n", nx, ny); @@ -1257,7 +1250,7 @@ static void cr_output_region(FILE * F, report_context * ctx, seen_region * sr) else { nx = r->x, ny = r->y; pnormalize(&nx, &ny, pl); - adjust_coordinates(f, &nx, &ny, pl, r); + adjust_coordinates(f, &nx, &ny, pl); } if (pl) { @@ -1308,6 +1301,7 @@ static void cr_output_region(FILE * F, report_context * ctx, seen_region * sr) if (r->display && r->display[0]) fprintf(F, "\"%s\";Beschr\n", r->display); if (fval(r->terrain, LAND_REGION)) { + assert(r->land); fprintf(F, "%d;Bauern\n", rpeasants(r)); if (fval(r, RF_ORCIFIED)) { fprintf(F, "1;Verorkt\n"); @@ -1338,7 +1332,7 @@ static void cr_output_region(FILE * F, report_context * ctx, seen_region * sr) fputs("1;mourning\n", F); } } - if (r->land->ownership) { + if (r->land && r->land->ownership) { fprintf(F, "%d;morale\n", r->land->morale); } } @@ -1398,7 +1392,7 @@ static void cr_output_region(FILE * F, report_context * ctx, seen_region * sr) plane *plx = rplane(r); pnormalize(&nx, &ny, plx); - adjust_coordinates(f, &nx, &ny, plx, r); + adjust_coordinates(f, &nx, &ny, plx); fprintf(F, "SCHEMEN %d %d\n", nx, ny); fprintf(F, "\"%s\";Name\n", rname(r, f->locale)); rl2 = rl2->next; @@ -1408,7 +1402,6 @@ static void cr_output_region(FILE * F, report_context * ctx, seen_region * sr) } /* describe both passed and inhabited regions */ - show_active_spells(r); if (fval(r, RF_TRAVELUNIT)) { bool seeunits = false, seeships = false; const attrib *ru; @@ -1441,13 +1434,13 @@ static void cr_output_region(FILE * F, report_context * ctx, seen_region * sr) } } if (sr->mode == see_unit || sr->mode == see_travel) { - cr_output_messages(F, r->msgs, f); - { - message_list *mlist = r_getmessages(r, f); - if (mlist) - cr_output_messages(F, mlist, f); - } - } + cr_output_messages(F, r->msgs, f); + { + message_list *mlist = r_getmessages(r, f); + if (mlist) + cr_output_messages(F, mlist, f); + } + } /* buildings */ for (b = rbuildings(r); b; b = b->next) { int fno = -1; @@ -1500,7 +1493,7 @@ report_computer(const char *filename, report_context * ctx, const char *charset) FILE *F = fopen(filename, "wt"); if (era < 0) { - era = get_param_int(global.parameters, "world.era", 2); + era = get_param_int(global.parameters, "world.era", 1); } if (F == NULL) { perror(filename); @@ -1623,7 +1616,7 @@ report_computer(const char *filename, report_context * ctx, const char *charset) int nx = r->x, ny = r->y; pnormalize(&nx, &ny, pl); - adjust_coordinates(f, &nx, &ny, pl, r); + adjust_coordinates(f, &nx, &ny, pl); if (!plid) fprintf(F, "BATTLE %d %d\n", nx, ny); else { diff --git a/src/economy.c b/src/economy.c index 5eedbfa9c..8cf46845b 100644 --- a/src/economy.c +++ b/src/economy.c @@ -93,7 +93,7 @@ static request entertainers[1024]; static request *nextentertainer; static int entertaining; -static int norders; +static unsigned int norders; static request *oa; #define RECRUIT_MERGE 1 @@ -123,13 +123,13 @@ int income(const unit * u) } } -static void scramble(void *data, int n, size_t width) +static void scramble(void *data, unsigned int n, size_t width) { - int j; + unsigned int j; char temp[64]; assert(width <= sizeof(temp)); for (j = 0; j != n; ++j) { - int k = rng_int() % n; + unsigned int k = rng_uint() % n; if (k == j) continue; memcpy(temp, (char *)data + j * width, width); @@ -162,7 +162,7 @@ static void expandorders(region * r, request * requests) oa = (request *)calloc(norders, sizeof(request)); for (o = requests; o; o = o->next) { if (o->qty > 0) { - int j; + unsigned int j; for (j = o->qty; j; j--) { oa[i] = *o; oa[i].unit->n = 0; @@ -297,7 +297,7 @@ static int horse_recruiters(const struct race *rc, int qty) if (rc->ec_flags & ECF_REC_ETHEREAL) return -1; if (rc->ec_flags & ECF_REC_HORSES) - return (int)(qty * 2 * rc->recruit_multi); + return (int)(qty * 2.0 * rc->recruit_multi); return -1; } @@ -354,7 +354,7 @@ static int do_recruiting(recruitment * recruits, int available) unit *u = req->unit; const race *rc = u_race(u); /* race is set in recruit() */ int number, dec; - float multi = 2.0F * rc->recruit_multi; + double multi = 2.0 * rc->recruit_multi; number = _min(req->qty, (int)(get / multi)); if (rc->recruitcost) { @@ -463,7 +463,6 @@ static int recruit_cost(const faction * f, const race * rc) static void recruit(unit * u, struct order *ord, request ** recruitorders) { - int n; region *r = u->region; plane *pl; request *o; @@ -471,9 +470,14 @@ static void recruit(unit * u, struct order *ord, request ** recruitorders) const faction *f = u->faction; const struct race *rc = u_race(u); const char *str; + int n; init_order(ord); - n = getuint(); + n = getint(); + if (n<=0) { + syntax_error(u, ord); + return; + } if (u->number == 0) { char token[128]; @@ -559,11 +563,15 @@ static void recruit(unit * u, struct order *ord, request ** recruitorders) return; } } - if (!playerrace(rc) || idle(u->faction)) { + if (!playerrace(rc)) { cmistake(u, ord, 139, MSG_EVENT); return; } + if (fval(u, UFL_HERO)) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_herorecruit", "")); + return; + } if (has_skill(u, SK_MAGIC)) { /* error158;de;{unit} in {region}: '{command}' - Magier arbeiten * grundstzlich nur alleine! */ @@ -971,21 +979,11 @@ void economics(region * r) remove_empty_units_in_region(r); for (u = r->units; u; u = u->next) { - order *ord; - bool destroyed = false; - if (u->number > 0) { - for (ord = u->orders; ord; ord = ord->next) { - keyword_t kwd = getkeyword(ord); - if (kwd == K_DESTROY) { - if (!destroyed) { - if (destroy_cmd(u, ord) != 0) - ord = NULL; - destroyed = true; - } - } - if (u->orders == NULL) { - break; - } + order *ord = u->thisorder; + keyword_t kwd = getkeyword(ord); + if (kwd == K_DESTROY) { + if (destroy_cmd(u, ord) == 0) { + fset(u, UFL_LONGACTION | UFL_NOTMOVING); } } } @@ -1040,7 +1038,7 @@ static void manufacture(unit * u, const item_type * itype, int want) i_change(&u->items, itype, n); if (want == INT_MAX) want = n; - ADDMSG(&u->faction->msgs, msg_message("manufacture", + ADDMSG(&u->faction->msgs, msg_message("produce", "unit region amount wanted resource", u, u->region, n, want, itype->rtype)); } @@ -1455,7 +1453,7 @@ static void create_potion(unit * u, const potion_type * ptype, int want) i_change(&u->items, ptype->itype, built); if (want == INT_MAX) want = built; - ADDMSG(&u->faction->msgs, msg_message("manufacture", + ADDMSG(&u->faction->msgs, msg_message("produce", "unit region amount wanted resource", u, u->region, built, want, ptype->itype->rtype)); break; @@ -1649,7 +1647,7 @@ static void expandbuying(region * r, request * buyorders) int multi; } trades[MAXLUXURIES], *trade; static int ntrades = 0; - int i, j; + int i; const luxury_type *ltype; if (ntrades == 0) { @@ -1678,6 +1676,7 @@ static void expandbuying(region * r, request * buyorders) * Gter pro Monat ist. j sind die Befehle, i der Index des * gehandelten Produktes. */ if (max_products > 0) { + unsigned int j; expandorders(r, buyorders); if (!norders) return; @@ -1780,8 +1779,8 @@ static void buy(unit * u, request ** buyorders, struct order *ord) kwd = init_order(ord); assert(kwd == K_BUY); - n = getuint(); - if (!n) { + n = getint(); + if (n<=0) { cmistake(u, ord, 26, MSG_COMMERCE); return; } @@ -1876,7 +1875,8 @@ static int tax_per_size[7] = { 0, 6, 12, 18, 24, 30, 36 }; static void expandselling(region * r, request * sellorders, int limit) { - int money, price, j, max_products; + int money, price, max_products; + unsigned int j; /* int m, n = 0; */ int maxsize = 0, maxeffsize = 0; int taxcollected = 0; @@ -2212,7 +2212,7 @@ static bool sell(unit * u, request ** sellorders, struct order *ord) static void expandstealing(region * r, request * stealorders) { const resource_type *rsilver = get_resourcetype(R_SILVER); - int i; + unsigned int j; assert(rsilver); @@ -2225,8 +2225,8 @@ static void expandstealing(region * r, request * stealorders) * u ist die beklaute unit. oa.unit ist die klauende unit. */ - for (i = 0; i != norders && oa[i].unit->n <= oa[i].unit->wants; i++) { - unit *u = findunitg(oa[i].no, r); + for (j = 0; j != norders && oa[j].unit->n <= oa[j].unit->wants; j++) { + unit *u = findunitg(oa[j].no, r); int n = 0; if (u && u->region == r) { n = get_pooled(u, rsilver, GET_ALL, INT_MAX); @@ -2250,15 +2250,15 @@ static void expandstealing(region * r, request * stealorders) n = 10; } if (n > 0) { - n = _min(n, oa[i].unit->wants); + n = _min(n, oa[j].unit->wants); use_pooled(u, rsilver, GET_ALL, n); - oa[i].unit->n = n; - change_money(oa[i].unit, n); + oa[j].unit->n = n; + change_money(oa[j].unit, n); ADDMSG(&u->faction->msgs, msg_message("stealeffect", "unit region amount", u, u->region, n)); } - add_income(oa[i].unit, IC_STEAL, oa[i].unit->wants, oa[i].unit->n); - fset(oa[i].unit, UFL_LONGACTION | UFL_NOTMOVING); + add_income(oa[j].unit, IC_STEAL, oa[j].unit->wants, oa[j].unit->n); + fset(oa[j].unit, UFL_LONGACTION | UFL_NOTMOVING); } free(oa); } @@ -2901,7 +2901,7 @@ static int do_work(unit * u, order * ord, request * o) static void expandloot(region * r, request * lootorders) { unit *u; - int i; + unsigned int i; int looted = 0; int startmoney = rmoney(r); @@ -2938,7 +2938,7 @@ static void expandloot(region * r, request * lootorders) static void expandtax(region * r, request * taxorders) { unit *u; - int i; + unsigned int i; expandorders(r, taxorders); if (!norders) @@ -2993,10 +2993,11 @@ void tax_cmd(unit * u, struct order *ord, request ** taxorders) return; } - max = getuint(); + max = getint(); - if (max == 0) + if (max <= 0) { max = INT_MAX; + } if (!playerrace(u_race(u))) { u->wants = _min(income(u), max); } @@ -3066,10 +3067,11 @@ void loot_cmd(unit * u, struct order *ord, request ** lootorders) return; } - max = getuint(); + max = getint(); - if (max == 0) + if (max <= 0) { max = INT_MAX; + } if (!playerrace(u_race(u))) { u->wants = _min(income(u), max); } @@ -3201,7 +3203,7 @@ void produce(struct region *r) continue; if (fval(u, UFL_LONGACTION) && u->thisorder == NULL) { - /* this message was already given in laws.setdefaults + /* this message was already given in laws.c:update_long_order cmistake(u, u->thisorder, 52, MSG_PRODUCE); */ continue; diff --git a/src/economy.test.c b/src/economy.test.c index b43a6d1fc..3feba7956 100644 --- a/src/economy.test.c +++ b/src/economy.test.c @@ -3,12 +3,19 @@ #include "economy.h" #include -#include +#include +#include +#include +#include +#include +#include #include #include -#include #include #include +#include + +#include #include #include @@ -114,6 +121,62 @@ static void test_steal_ocean(CuTest * tc) { test_cleanup(); } +static struct unit *create_recruiter(void) { + region *r; + faction *f; + unit *u; + const resource_type* rtype; + + test_cleanup(); + test_create_world(); + + r=findregion(0, 0); + rsetpeasants(r, 999); + f = test_create_faction(rc_find("human")); + u = test_create_unit(f, r); + rtype = get_resourcetype(R_SILVER); + change_resource(u, rtype, 1000); + return u; +} + +static void test_heroes_dont_recruit(CuTest * tc) { + unit *u; + order *ord; + const message_type *msg_types[1]; + + test_cleanup(); + msg_types[0] = register_msg("error_herorecruit", 3, "unit:unit", "region:region", "command:order"); + + u = create_recruiter(); + fset(u, UFL_HERO); + ord = create_order(K_RECRUIT, default_locale, "1"); + unit_addorder(u, ord); + + economics(u->region); + + CuAssertIntEquals(tc, 1, u->number); + assert_messages(tc, u->faction->msgs->begin, msg_types, 1, true, 0); + + test_cleanup(); +} + +static void test_normals_recruit(CuTest * tc) { + unit *u; + order *ord; + + test_cleanup(); + + u = create_recruiter(); + ord = create_order(K_RECRUIT, default_locale, "1"); + unit_addorder(u, ord); + + economics(u->region); + + CuAssertIntEquals(tc, 2, u->number); + + test_cleanup(); +} + CuSuite *get_economy_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -122,5 +185,7 @@ CuSuite *get_economy_suite(void) SUITE_ADD_TEST(suite, test_steal_okay); SUITE_ADD_TEST(suite, test_steal_ocean); SUITE_ADD_TEST(suite, test_steal_nosteal); + SUITE_ADD_TEST(suite, test_normals_recruit); + SUITE_ADD_TEST(suite, test_heroes_dont_recruit); return suite; } diff --git a/src/eressea.c b/src/eressea.c index 4bfe59daf..14cce6267 100755 --- a/src/eressea.c +++ b/src/eressea.c @@ -25,6 +25,7 @@ #include "report.h" #include "items.h" #include "creport.h" +#include "jsreport.h" #include "names.h" #include "wormhole.h" #include "spells.h" @@ -56,6 +57,7 @@ void game_init(void) register_nr(); register_cr(); + register_jsreport(); register_races(); register_spells(); diff --git a/src/give.c b/src/give.c index 7b9d2a3fb..f9879b9dd 100644 --- a/src/give.c +++ b/src/give.c @@ -1,4 +1,4 @@ -/* +/* +-------------------+ Christian Schlittchen | | Enno Rehling | Eressea PBEM host | Katja Zedel @@ -48,18 +48,16 @@ #include /* Wieviel Fremde eine Partei pro Woche aufnehmen kangiven */ -#define MAXNEWBIES 5 #define RESERVE_DONATIONS /* shall we reserve objects given to us by other factions? */ #define RESERVE_GIVE /* reserve anything that's given from one unit to another? */ +static int max_transfers(void) { + return get_param_int(global.parameters, "rules.give.max_men", 5); +} + static int GiveRestriction(void) { - static int value = -1; - if (value < 0) { - const char *str = get_param(global.parameters, "GiveRestriction"); - value = str ? atoi(str) : 0; - } - return value; + return get_param_int(global.parameters, "GiveRestriction", 0); } static void feedback_give_not_allowed(unit * u, order * ord) @@ -128,7 +126,7 @@ static bool limited_give(const item_type * type) int give_quota(const unit * src, const unit * dst, const item_type * type, int n) { - float divisor; + double divisor; if (!limited_give(type)) { return n; @@ -241,6 +239,7 @@ message * give_men(int n, unit * u, unit * u2, struct order *ord) int k = 0; int error = 0; message * msg; + int maxt = max_transfers(); assert(u2); @@ -300,7 +299,7 @@ message * give_men(int n, unit * u, unit * u2, struct order *ord) error = 96; } else if (u->faction != u2->faction) { - if (u2->faction->newbies + n > MAXNEWBIES) { + if (maxt >= 0 && u2->faction->newbies + n > maxt) { error = 129; } else if (u_race(u) != u2->faction->race) { @@ -333,7 +332,7 @@ message * give_men(int n, unit * u, unit * u2, struct order *ord) if (has_skill(u2, SK_ALCHEMY) && !has_skill(u, SK_ALCHEMY)) k += n; - /* Wenn Parteigrenzen berschritten werden */ + /* Wenn Parteigrenzen überschritten werden */ if (u2->faction != u->faction) k += n; @@ -355,14 +354,14 @@ message * give_men(int n, unit * u, unit * u2, struct order *ord) freset(u2, UFL_HERO); } - /* Einheiten von Schiffen knnen nicht NACH in von - * Nicht-alliierten bewachten Regionen ausfhren */ + /* Einheiten von Schiffen können nicht NACH in von + * Nicht-alliierten bewachten Regionen ausführen */ sh = leftship(u); if (sh) { set_leftship(u2, sh); } transfermen(u, u2, n); - if (u->faction != u2->faction) { + if (maxt >= 0 && u->faction != u2->faction) { u2->faction->newbies += n; } } @@ -401,15 +400,15 @@ message * disband_men(int n, unit * u, struct order *ord) { void give_unit(unit * u, unit * u2, order * ord) { - region *r = u->region; - int n = u->number; + int maxt = max_transfers(); + assert(u); if (!rule_transfermen() && u->faction != u2->faction) { cmistake(u, ord, 74, MSG_COMMERCE); return; } - if (u && unit_has_cursed_item(u)) { + if (unit_has_cursed_item(u)) { cmistake(u, ord, 78, MSG_COMMERCE); return; } @@ -424,6 +423,7 @@ void give_unit(unit * u, unit * u2, order * ord) } if (u2 == NULL) { + region *r = u->region; message *msg; if (fval(r->terrain, SEA_REGION)) { msg = disband_men(u->number, u, ord); @@ -473,9 +473,11 @@ void give_unit(unit * u, unit * u2, order * ord) cmistake(u, ord, 105, MSG_COMMERCE); return; } - if (u2->faction->newbies + n > MAXNEWBIES) { - cmistake(u, ord, 129, MSG_COMMERCE); - return; + if (maxt >= 0 && u->faction != u2->faction) { + if (u2->faction->newbies + u->number > maxt) { + cmistake(u, ord, 129, MSG_COMMERCE); + return; + } } if (u_race(u) != u2->faction->race) { if (u2->faction->race != get_race(RC_HUMAN)) { @@ -511,13 +513,13 @@ void give_unit(unit * u, unit * u2, order * ord) cmistake(u, ord, 156, MSG_COMMERCE); return; } - add_give(u, u2, n, n, get_resourcetype(R_PERSON), ord, 0); + add_give(u, u2, u->number, u->number, get_resourcetype(R_PERSON), ord, 0); u_setfaction(u, u2->faction); - u2->faction->newbies += n; + u2->faction->newbies += u->number; } bool can_give_to(unit *u, unit *u2) { - /* Damit Tarner nicht durch die Fehlermeldung enttarnt werden knnen */ + /* Damit Tarner nicht durch die Fehlermeldung enttarnt werden können */ if (!u2) { return false; } @@ -592,7 +594,7 @@ void give_cmd(unit * u, order * ord) else if (p == P_HERBS) { bool given = false; - if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { + if ((u_race(u)->ec_flags & ECF_KEEP_ITEM) && u2 != NULL) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "race_nogive", "race", u_race(u))); return; @@ -612,7 +614,7 @@ void give_cmd(unit * u, order * ord) item *itm = *itmp; const item_type *itype = itm->type; if (fval(itype, ITF_HERB) && itm->number > 0) { - /* give_item ndert im fall,das man alles bergibt, die + /* give_item ändert im fall,das man alles übergibt, die * item-liste der unit, darum continue vor pointerumsetzten */ if (give_item(itm->number, itm->type, u, u2, ord) == 0) { given = true; @@ -657,7 +659,7 @@ void give_cmd(unit * u, order * ord) if (!s || *s == 0) { /* GIVE ALL items that you have */ /* do these checks once, not for each item we have: */ - if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { + if ((u_race(u)->ec_flags & ECF_KEEP_ITEM) && u2 != NULL) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "race_nogive", "race", u_race(u))); return; @@ -668,8 +670,8 @@ void give_cmd(unit * u, order * ord) return; } - /* fr alle items einmal prfen, ob wir mehr als von diesem Typ - * reserviert ist besitzen und diesen Teil dann bergeben */ + /* für alle items einmal prüfen, ob wir mehr als von diesem Typ + * reserviert ist besitzen und diesen Teil dann übergeben */ if (u->items) { item **itmp = &u->items; while (*itmp) { @@ -701,7 +703,7 @@ void give_cmd(unit * u, order * ord) } } } - else if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { + else if ((u_race(u)->ec_flags & ECF_KEEP_ITEM) && u2 != NULL) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "race_nogive", "race", u_race(u))); } @@ -760,7 +762,7 @@ void give_cmd(unit * u, order * ord) } if (u2 != NULL) { - if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { + if ((u_race(u)->ec_flags & ECF_KEEP_ITEM) && u2 != NULL) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "race_nogive", "race", u_race(u))); return; diff --git a/src/give.test.c b/src/give.test.c index 5437dfa5b..a5714f445 100644 --- a/src/give.test.c +++ b/src/give.test.c @@ -3,6 +3,7 @@ #include "give.h" #include "economy.h" +#include #include #include #include @@ -34,6 +35,10 @@ static void setup_give(struct give *env) { env->dst = env->f2 ? test_create_unit(env->f2, env->r) : 0; env->itype = it_get_or_create(rt_get_or_create("money")); env->itype->flags |= ITF_HERB; + if (env->f1 && env->f2) { + ally * al = ally_add(&env->f2->allies, env->f1); + al->status = HELP_GIVE; + } } static void test_give_unit_to_peasants(CuTest * tc) { @@ -49,6 +54,25 @@ static void test_give_unit_to_peasants(CuTest * tc) { test_cleanup(); } +static void test_give_unit(CuTest * tc) { + struct give env; + test_cleanup(); + env.f1 = test_create_faction(0); + env.f2 = test_create_faction(0); + setup_give(&env); + env.r->terrain = test_create_terrain("ocean", SEA_REGION); + set_param(&global.parameters, "rules.give.max_men", "0"); + give_unit(env.src, env.dst, NULL); + CuAssertPtrEquals(tc, env.f1, env.src->faction); + CuAssertIntEquals(tc, 0, env.f2->newbies); + set_param(&global.parameters, "rules.give.max_men", "-1"); + give_unit(env.src, env.dst, NULL); + CuAssertPtrEquals(tc, env.f2, env.src->faction); + CuAssertIntEquals(tc, 1, env.f2->newbies); + CuAssertPtrEquals(tc, 0, env.f1->units); + test_cleanup(); +} + static void test_give_unit_in_ocean(CuTest * tc) { struct give env; test_cleanup(); @@ -72,6 +96,36 @@ static void test_give_men(CuTest * tc) { test_cleanup(); } +static void test_give_men_limit(CuTest * tc) { + struct give env; + message *msg; + test_cleanup(); + env.f2 = test_create_faction(0); + env.f1 = test_create_faction(0); + setup_give(&env); + set_param(&global.parameters, "rules.give.max_men", "1"); + + /* below the limit, give men, increase newbies counter */ + usetcontact(env.dst, env.src); + msg = give_men(1, env.src, env.dst, NULL); + CuAssertStrEquals(tc, "give_person", (const char *)msg->parameters[0].v); + CuAssertIntEquals(tc, 2, env.dst->number); + CuAssertIntEquals(tc, 0, env.src->number); + CuAssertIntEquals(tc, 1, env.f2->newbies); + msg_release(msg); + + /* beyond the limit, do nothing */ + usetcontact(env.src, env.dst); + msg = give_men(2, env.dst, env.src, NULL); + CuAssertStrEquals(tc, "error129", (const char *)msg->parameters[3].v); + CuAssertIntEquals(tc, 2, env.dst->number); + CuAssertIntEquals(tc, 0, env.src->number); + CuAssertIntEquals(tc, 0, env.f1->newbies); + msg_release(msg); + + test_cleanup(); +} + static void test_give_men_in_ocean(CuTest * tc) { struct give env; message * msg; @@ -247,12 +301,14 @@ CuSuite *get_give_suite(void) CuSuite *suite = CuSuiteNew(); SUITE_ADD_TEST(suite, test_give); SUITE_ADD_TEST(suite, test_give_men); + SUITE_ADD_TEST(suite, test_give_men_limit); SUITE_ADD_TEST(suite, test_give_men_in_ocean); SUITE_ADD_TEST(suite, test_give_men_none); SUITE_ADD_TEST(suite, test_give_men_too_many); SUITE_ADD_TEST(suite, test_give_men_other_faction); SUITE_ADD_TEST(suite, test_give_men_requires_contact); SUITE_ADD_TEST(suite, test_give_men_not_to_self); + SUITE_ADD_TEST(suite, test_give_unit); SUITE_ADD_TEST(suite, test_give_unit_in_ocean); SUITE_ADD_TEST(suite, test_give_unit_to_peasants); SUITE_ADD_TEST(suite, test_give_peasants); diff --git a/src/gmtool.c b/src/gmtool.c index e92299f2b..3c0ad1136 100644 --- a/src/gmtool.c +++ b/src/gmtool.c @@ -65,6 +65,7 @@ static int g_quit; int force_color = 0; +newfaction * new_players = 0; state *current_state = NULL; @@ -77,7 +78,7 @@ static WINDOW *hstatus; static void init_curses(void) { - short fg, bg; + int fg, bg; initscr(); if (has_colors() || force_color) { @@ -93,7 +94,7 @@ static void init_curses(void) #endif for (fg = 0; fg != 8; ++fg) { for (bg = 0; bg != 2; ++bg) { - init_pair(fg + 8 * bg, fg, bg ? hcol : bcol); + init_pair((short)(fg + 8 * bg), (short)fg, (short)(bg ? hcol : bcol)); } } @@ -248,6 +249,8 @@ static void paint_map(window * wnd, const state * st) int cols = getmaxx(win); int vx, vy; + assert(st); + if (!st) return; lines = lines / THEIGHT; cols = cols / TWIDTH; for (vy = 0; vy != lines; ++vy) { @@ -259,11 +262,9 @@ static void paint_map(window * wnd, const state * st) int xp = vx * TWIDTH + (vy & 1) * TWIDTH / 2; int nx, ny; if (mr) { - if (st) { - cnormalize(&mr->coord, &nx, &ny); - if (tagged_region(st->selected, nx, ny)) { - attr |= A_REVERSE; - } + cnormalize(&mr->coord, &nx, &ny); + if (tagged_region(st->selected, nx, ny)) { + attr |= A_REVERSE; } if (mr->r && (mr->r->flags & RF_MAPPER_HIGHLIGHT)) hl = 1; @@ -423,7 +424,7 @@ static void paint_info_region(window * wnd, const state * st) wattroff(win, A_BOLD | COLOR_PAIR(COLOR_YELLOW)); for (u = r->units; u && line < maxline; u = u->next) { mvwprintw(win, line, 1, "%.4s ", itoa36(u->no)); - mvwaddnstr(win, line++, 6, (char *)u->name, size - 5); + mvwaddnstr(win, line++, 6, unit_getname(u), size - 5); } } } @@ -761,6 +762,29 @@ static void select_regions(state * st, int selectmode) st->wnd_map->update |= 3; } +void loaddata(state *st) { + char datafile[MAX_PATH]; + + askstring(st->wnd_status->handle, "save as:", datafile, sizeof(datafile)); + if (strlen(datafile) > 0) { + create_backup(datafile); + readgame(datafile, false); + st->modified = 0; + } +} + +void savedata(state *st) { + char datafile[MAX_PATH]; + + askstring(st->wnd_status->handle, "save as:", datafile, sizeof(datafile)); + if (strlen(datafile) > 0) { + create_backup(datafile); + remove_empty_units(); + writegame(datafile); + st->modified = 0; + } +} + static void handlekey(state * st, int c) { window *wnd; @@ -770,7 +794,7 @@ static void handlekey(state * st, int c) region *r; char sbuffer[80]; static char kbuffer[80]; - int n, nx, ny; + int n, nx, ny, minpop, maxpop; switch (c) { case FAST_RIGHT: @@ -816,25 +840,27 @@ static void handlekey(state * st, int c) case 'S': case KEY_SAVE: case KEY_F(2): - /* if (st->modified) */ { - char datafile[MAX_PATH]; - - askstring(st->wnd_status->handle, "save as:", datafile, sizeof(datafile)); - if (strlen(datafile) > 0) { - create_backup(datafile); - remove_empty_units(); - writegame(datafile); - st->modified = 0; - } - } + savedata(st); + break; + case KEY_F(3): + case KEY_OPEN: + loaddata(st); break; case 'B': - /* - make_block(st->cursor.x, st->cursor.y, 6, select_terrain(st, NULL)); - */ + if (!new_players) { + sprintf(sbuffer, "%s/newfactions", basepath()); + new_players = read_newfactions(sbuffer); + } cnormalize(&st->cursor, &nx, &ny); - n = rng_int() % 8 + 8; - build_island_e3(nx, ny, n, n * 3); + minpop = get_param_int(global.parameters, "seed.population.min", 8); + maxpop = get_param_int(global.parameters, "seed.population.max", minpop); + if (maxpop > minpop) { + n = rng_int() % (maxpop - minpop) + minpop; + } + else { + n = minpop; + } + build_island_e3(&new_players, nx, ny, n, n * 3); st->modified = 1; st->wnd_info->update |= 1; st->wnd_status->update |= 1; @@ -929,6 +955,7 @@ static void handlekey(state * st, int c) } } break; + case 'f': case 0x14: /* C-t */ terraform_at(&st->cursor, select_terrain(st, NULL)); st->modified = 1; @@ -1011,6 +1038,7 @@ static void handlekey(state * st, int c) statusline(st->wnd_status->handle, "tag-"); doupdate(); switch (getch()) { + case 'f': case 't': terraform_selection(st->selected, select_terrain(st, NULL)); st->modified = 1; @@ -1033,8 +1061,11 @@ static void handlekey(state * st, int c) tag_region(st->selected, nx, ny); break; case 'A': - sprintf(sbuffer, "%s/newfactions", basepath()); - seed_players(sbuffer, false); + if (!new_players) { + sprintf(sbuffer, "%s/newfactions", basepath()); + new_players = read_newfactions(sbuffer); + } + seed_players(&new_players, false); st->wnd_map->update |= 1; break; case '/': @@ -1313,15 +1344,14 @@ const char *prompt) return buffer[0] != 0; } -void seed_players(const char *filename, bool new_island) +void seed_players(newfaction **players, bool new_island) { - newfaction *players = read_newfactions(filename); - if (players != NULL) { - while (players) { - int n = listlen(players); + if (players) { + while (*players) { + int n = listlen(*players); int k = (n + ISLANDSIZE - 1) / ISLANDSIZE; k = n / k; - n = autoseed(&players, k, new_island ? 0 : TURNS_PER_ISLAND); + n = autoseed(players, k, new_island ? 0 : TURNS_PER_ISLAND); if (n == 0) { break; } diff --git a/src/gmtool.h b/src/gmtool.h index ae2cea39a..d5396a615 100644 --- a/src/gmtool.h +++ b/src/gmtool.h @@ -20,6 +20,7 @@ extern "C" { struct state; struct region; struct terrain_type; + struct newfaction; int gmmain(int argc, char *argv[]); int curses_readline(struct lua_State *L, char *buffer, size_t size, @@ -35,7 +36,7 @@ extern "C" { void state_close(struct state *); void make_block(int x, int y, int radius, const struct terrain_type *terrain); - void seed_players(const char *filename, bool new_island); + void seed_players(struct newfaction **players, bool new_island); #ifdef __cplusplus } diff --git a/src/helpers.c b/src/helpers.c index 4690023e9..29038afb3 100644 --- a/src/helpers.c +++ b/src/helpers.c @@ -58,7 +58,7 @@ lua_giveitem(unit * s, unit * d, const item_type * itype, int n, struct order *o tolua_pushusertype(L, s, TOLUA_CAST "unit"); tolua_pushusertype(L, d, TOLUA_CAST "unit"); tolua_pushstring(L, iname); - tolua_pushnumber(L, (lua_Number)n); + lua_pushinteger(L, n); if (lua_pcall(L, 4, 1, 0) != 0) { const char *error = lua_tostring(L, -1); @@ -121,7 +121,7 @@ produce_resource(region * r, const resource_type * rtype, int norders) lua_getglobal(L, fname); if (lua_isfunction(L, -1)) { tolua_pushusertype(L, (void *)r, TOLUA_CAST "region"); - tolua_pushnumber(L, (lua_Number)norders); + lua_pushinteger(L, norders); if (lua_pcall(L, 2, 0, 0) != 0) { const char *error = lua_tostring(L, -1); @@ -177,8 +177,8 @@ static int lua_callspell(castorder * co) int nparam = 4; tolua_pushusertype(L, r, TOLUA_CAST "region"); tolua_pushusertype(L, caster, TOLUA_CAST "unit"); - tolua_pushnumber(L, (lua_Number)co->level); - tolua_pushnumber(L, (lua_Number)co->force); + lua_pushinteger(L, co->level); + lua_pushnumber(L, co->force); if (co->sp->parameter && co->par->length) { const char *synp = co->sp->parameter; int i = 0; @@ -267,7 +267,7 @@ lua_changeresource(unit * u, const struct resource_type *rtype, int delta) lua_getglobal(L, fname); if (lua_isfunction(L, -1)) { tolua_pushusertype(L, u, TOLUA_CAST "unit"); - tolua_pushnumber(L, (lua_Number)delta); + lua_pushinteger(L, delta); if (lua_pcall(L, 2, 1, 0) != 0) { const char *error = lua_tostring(L, -1); @@ -363,7 +363,7 @@ lua_wage(const region * r, const faction * f, const race * rc, int in_turn) tolua_pushusertype(L, (void *)r, TOLUA_CAST "region"); tolua_pushusertype(L, (void *)f, TOLUA_CAST "faction"); tolua_pushstring(L, rc ? rc->_name : 0); - tolua_pushnumber(L, (lua_Number)in_turn); + lua_pushinteger(L, in_turn); if (lua_pcall(L, 3, 1, 0) != 0) { const char *error = lua_tostring(L, -1); @@ -416,7 +416,7 @@ static double lua_building_taxes(building * b, int level) lua_getglobal(L, fname); if (lua_isfunction(L, -1)) { tolua_pushusertype(L, (void *)b, TOLUA_CAST "building"); - tolua_pushnumber(L, level); + lua_pushinteger(L, level); if (lua_pcall(L, 2, 1, 0) != 0) { const char *error = lua_tostring(L, -1); @@ -508,7 +508,7 @@ struct order *ord) lua_getglobal(L, fname); if (lua_isfunction(L, -1)) { tolua_pushusertype(L, (void *)u, TOLUA_CAST "unit"); - tolua_pushnumber(L, (lua_Number)amount); + lua_pushinteger(L, amount); if (lua_pcall(L, 2, 1, 0) != 0) { const char *error = lua_tostring(L, -1); diff --git a/src/items.c b/src/items.c index d7c9efd5e..5e9a357e6 100644 --- a/src/items.c +++ b/src/items.c @@ -81,7 +81,7 @@ use_speedsail(struct unit *u, const struct item_type *itype, int amount, struct order *ord) { curse *c; - float effect; + double effect; ship *sh = u->ship; if (!sh) { cmistake(u, ord, 20, MSG_MOVE); @@ -120,7 +120,7 @@ struct order *ord) } for (i = 0; i != amount; ++i) { int effect, duration = 2; - float force; + double force; spell *sp = find_spell("antimagiczone"); attrib **ap = &r->attribs; unused_arg(ord); @@ -132,7 +132,7 @@ struct order *ord) /* Hlt Sprche bis zu einem summierten Gesamtlevel von power aus. * Jeder Zauber reduziert die 'Lebenskraft' (vigour) der Antimagiezone * um seine Stufe */ - force = (float)effect * 20; /* Stufe 5 =~ 100 */ + force = effect * 20; /* Stufe 5 =~ 100 */ /* Regionszauber auflsen */ while (*ap && force > 0) { @@ -163,8 +163,8 @@ struct order *ord) } if (force > 0) { - create_curse(u, &r->attribs, ct_find("antimagiczone"), (float)force, duration, - (float)effect, 0); + create_curse(u, &r->attribs, ct_find("antimagiczone"), force, duration, + effect, 0); } } use_pooled(u, rt_crystal, GET_DEFAULT, amount); diff --git a/src/items/CMakeLists.txt b/src/items/CMakeLists.txt index 5046403d1..9ab324e77 100644 --- a/src/items/CMakeLists.txt +++ b/src/items/CMakeLists.txt @@ -1,4 +1,9 @@ PROJECT(items C) + +SET(_TEST_FILES +xerewards.test.c +) + SET(_FILES artrewards.c demonseye.c @@ -14,4 +19,8 @@ FOREACH(_FILE ${_FILES}) ENDFOREACH(_FILE) SET(ITEMS_SRC ${_SOURCES} PARENT_SCOPE) - \ No newline at end of file +FOREACH(_FILE ${_TEST_FILES}) + LIST(APPEND _TESTS ${PROJECT_NAME}/${_FILE}) +ENDFOREACH(_FILE) +SET(ITEMS_TESTS ${_TESTS} PARENT_SCOPE) + diff --git a/src/items/xerewards.c b/src/items/xerewards.c index b20fb19bb..1868d3a67 100644 --- a/src/items/xerewards.c +++ b/src/items/xerewards.c @@ -39,7 +39,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include -static int +int use_skillpotion(struct unit *u, const struct item_type *itype, int amount, struct order *ord) { @@ -59,12 +59,10 @@ struct order *ord) } } ADDMSG(&u->faction->msgs, msg_message("skillpotion_use", "unit", u)); - - change_resource(u, itype->rtype, -amount); - return 0; + return amount; } -static int +int use_manacrystal(struct unit *u, const struct item_type *itype, int amount, struct order *ord) { @@ -82,8 +80,7 @@ struct order *ord) ADDMSG(&u->faction->msgs, msg_message("manacrystal_use", "unit aura", u, sp)); - change_resource(u, itype->rtype, -amount); - return 0; + return amount; } void register_xerewards(void) diff --git a/src/items/xerewards.h b/src/items/xerewards.h index 36b6ca18d..189032891 100644 --- a/src/items/xerewards.h +++ b/src/items/xerewards.h @@ -22,7 +22,12 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. extern "C" { #endif - extern void register_xerewards(void); + struct unit; + struct item_type; + struct order; + void register_xerewards(void); + int use_skillpotion(struct unit *u, const struct item_type *itype, int amount, struct order *ord); + int use_manacrystal(struct unit *u, const struct item_type *itype, int amount, struct order *ord); #ifdef __cplusplus } diff --git a/src/items/xerewards.test.c b/src/items/xerewards.test.c new file mode 100644 index 000000000..5ce7716f3 --- /dev/null +++ b/src/items/xerewards.test.c @@ -0,0 +1,39 @@ +#include + +#include "xerewards.h" + +#include +#include +#include +#include + +#include +#include + +static void test_manacrystal(CuTest *tc) { + test_cleanup(); + test_create_world(); + test_cleanup(); +} + +static void test_skillpotion(CuTest *tc) { + unit *u; + const struct item_type *itype; + + test_cleanup(); + test_create_world(); + u = test_create_unit(test_create_faction(NULL), findregion(0, 0)); + itype = test_create_itemtype("skillpotion"); + change_resource(u, itype->rtype, 2); + CuAssertIntEquals(tc, 1, use_skillpotion(u, itype, 1, NULL)); + test_cleanup(); +} + +CuSuite *get_xerewards_suite(void) +{ + CuSuite *suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_manacrystal); + SUITE_ADD_TEST(suite, test_skillpotion); + return suite; +} + diff --git a/src/json.c b/src/json.c index 47a7a02cf..1fb2adb27 100644 --- a/src/json.c +++ b/src/json.c @@ -33,11 +33,11 @@ int json_import(struct stream * out) { cJSON *j; for (j = child->child; j; j = j->next) { cJSON *attr; - unsigned int id = 0; + int id = 0; int x = 0, y = 0; region * r; - id = (unsigned int)atol(j->string); + id = atoi(j->string); if ((attr = cJSON_GetObjectItem(j, "x")) != 0 && attr->type == cJSON_Number) x = attr->valueint; if ((attr = cJSON_GetObjectItem(j, "y")) != 0 && attr->type == cJSON_Number) y = attr->valueint; r = new_region(x, y, 0, id); diff --git a/src/jsreport.c b/src/jsreport.c new file mode 100644 index 000000000..6d9f710c2 --- /dev/null +++ b/src/jsreport.c @@ -0,0 +1,85 @@ +#include "reports.h" +#include "jsreport.h" +#include +#include +#include +#include + +#include + +#include +#include +#include + +static void coor_to_tiled(int *x, int *y) { + *y = -*y; + *x = *x - (*y + 1) / 2; +} + +static void coor_from_tiled(int *x, int *y) { + *x = *x + (*y + 1) / 2; + *y = -*y; +} + +static int report_json(const char *filename, report_context * ctx, const char *charset) +{ + if (get_param_int(global.parameters, "feature.jsreport.enable", 0) != 0) { + FILE * F = fopen(filename, "w"); + if (F) { + int x, y, minx = INT_MAX, maxx = INT_MIN, miny = INT_MAX, maxy = INT_MIN; + seen_region *sr; + region *r; + /* traverse all regions */ + for (sr = NULL, r = ctx->first; sr == NULL && r != ctx->last; r = r->next) { + sr = find_seen(ctx->seen, r); + } + for (; sr != NULL; sr = sr->next) { + int tx = sr->r->x; + int ty = sr->r->y; + coor_to_tiled(&tx, &ty); + if (ty < miny) miny = ty; + else if (ty > maxy) maxy = ty; + if (tx < minx) minx = tx; + else if (tx > maxx) maxx = tx; + } + if (maxx >= minx && maxy >= miny) { + int w = maxx - minx + 1, h = maxy - miny + 1; + fputs("{ \"orientation\":\"hexagonal\",\"staggeraxis\":\"y\",", F); + fprintf(F, "\"staggerindex\":\"%s\", \"height\":%d, \"width\":%d, \"layers\":[", (miny & 1) ? "odd" : "even", h, w); + fprintf(F, "{ \"height\":%d, \"width\":%d, ", h, w); + fputs("\"visible\":true, \"opacity\":1, \"type\":\"tilelayer\", \"name\":\"terrain\", \"x\":0, \"y\":0, \"data\":[", F); + for (y = miny; y <= maxy; ++y) { + for (x = minx; x <= maxx; ++x) { + int data = 0; + int tx = x, ty = y; + coor_from_tiled(&tx, &ty); + r = findregion(tx, ty); + if (r) { + sr = find_seen(ctx->seen, r); + if (sr) { + terrain_t ter = oldterrain(r->terrain); + if (ter == NOTERRAIN) { + log_warning("report_json: %s has no terrain id\n", r->terrain->_name); + } + data = 1 + (int)ter; + } + } + fprintf(F, "%d", data); + if (x != maxx || y != maxy) fputs(", ", F); + } + } + fputs("]}], \"tilesets\": [{\"firstgid\": 1, \"image\": \"magellan.png\", \"imageheight\": 192, \"imagewidth\": 256," + "\"margin\": 0, \"name\": \"hextiles\", \"properties\": { }, \"spacing\": 0, " + "\"tileheight\" : 64, \"tilewidth\" : 64 }], \"tilewidth\": 64, \"tileheight\": 96}", F); + } + return 0; + } + return -1; + } + return 0; +} + +void register_jsreport(void) +{ + register_reporttype("json", &report_json, 1 << O_JSON); +} diff --git a/src/jsreport.h b/src/jsreport.h new file mode 100644 index 000000000..fa3f7b115 --- /dev/null +++ b/src/jsreport.h @@ -0,0 +1,24 @@ +#pragma once +/* ++-------------------+ Christian Schlittchen +| | Enno Rehling +| Eressea PBEM host | Katja Zedel +| (c) 1998 - 2003 | Henning Peters +| | Ingo Wilken ++-------------------+ Stefan Reich + +This program may not be used, modified or distributed +without prior permission by the authors of Eressea. +*/ +#ifndef H_GC_JSREPORT +#define H_GC_JSREPORT +#ifdef __cplusplus +extern "C" { +#endif + + void register_jsreport(void); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/kernel/alliance.test.c b/src/kernel/alliance.test.c index ad936fac9..98e60e943 100644 --- a/src/kernel/alliance.test.c +++ b/src/kernel/alliance.test.c @@ -55,6 +55,9 @@ static void test_alliance_join(CuTest *tc) { setalliance(fix.f2, al); CuAssertPtrEquals(tc, fix.f1, alliance_get_leader(al)); CuAssertTrue(tc, is_allied(fix.f1, fix.f2)); + setalliance(fix.f1, 0); + CuAssertPtrEquals(tc, fix.f2, alliance_get_leader(al)); + CuAssertTrue(tc, !is_allied(fix.f1, fix.f2)); test_cleanup(); } diff --git a/src/kernel/build.c b/src/kernel/build.c index cfebbfff7..37006e968 100644 --- a/src/kernel/build.c +++ b/src/kernel/build.c @@ -101,7 +101,7 @@ static void destroy_road(unit * u, int nmax, struct order *ord) else { unit *u2; region *r = u->region; - short road, n = (short)nmax; + int road, n = nmax; if (nmax > SHRT_MAX) { n = SHRT_MAX; @@ -131,7 +131,7 @@ static void destroy_road(unit * u, int nmax, struct order *ord) if (willdo > SHRT_MAX) road = 0; else - road = road - (short)willdo; + road = (short)(road - willdo); rsetroad(r, d, road); ADDMSG(&u->faction->msgs, msg_message("destroy_road", "unit from to", u, r, r2)); @@ -151,7 +151,12 @@ int destroy_cmd(unit * u, struct order *ord) int n = INT_MAX; if (u->number < 1) - return 0; + return 1; + + if (fval(u, UFL_LONGACTION)) { + cmistake(u, ord, 52, MSG_PRODUCE); + return 52; + } init_order(ord); s = gettoken(token, sizeof(token)); @@ -164,8 +169,7 @@ int destroy_cmd(unit * u, struct order *ord) if (s && *s) { n = atoi((const char *)s); if (n <= 0) { - cmistake(u, ord, 288, MSG_PRODUCE); - return 0; + n = INT_MAX; } } @@ -179,11 +183,11 @@ int destroy_cmd(unit * u, struct order *ord) if (u != building_owner(b)) { cmistake(u, ord, 138, MSG_PRODUCE); - return 0; + return 138; } if (fval(b->type, BTF_INDESTRUCTIBLE)) { cmistake(u, ord, 138, MSG_PRODUCE); - return 0; + return 138; } if (n >= b->size) { /* destroy completly */ @@ -209,11 +213,11 @@ int destroy_cmd(unit * u, struct order *ord) if (u != ship_owner(sh)) { cmistake(u, ord, 138, MSG_PRODUCE); - return 0; + return 138; } if (fval(r->terrain, SEA_REGION)) { cmistake(u, ord, 14, MSG_EVENT); - return 0; + return 14; } if (n >= (sh->size * 100) / sh->type->construction->maxsize) { @@ -238,11 +242,11 @@ int destroy_cmd(unit * u, struct order *ord) } else { cmistake(u, ord, 138, MSG_PRODUCE); - return 0; + return 138; } if (con) { - /* TODO: Nicht an ZERSTRE mit Punktangabe angepat! */ + /* TODO: Nicht an ZERSTRE mit Punktangabe angepasst! */ int c; for (c = 0; con->materials[c].number; ++c) { const requirement *rq = con->materials + c; @@ -360,7 +364,7 @@ void build_road(region * r, unit * u, int size, direction_t d) /* n is now modified by several special effects, so we have to * minimize it again to make sure the road will not grow beyond * maximum. */ - rsetroad(r, d, rroad(r, d) + (short)n); + rsetroad(r, d, rroad(r, d) + n); if (u_race(u) == get_race(RC_STONEGOLEM)) { int golemsused = n / GOLEM_STONE; diff --git a/src/kernel/build.test.c b/src/kernel/build.test.c index 3ee3cf056..2befe6733 100644 --- a/src/kernel/build.test.c +++ b/src/kernel/build.test.c @@ -204,7 +204,8 @@ static void test_build_building_no_materials(CuTest *tc) { btype = bt_find("castle"); assert(btype); set_level(u, SK_BUILDING, 1); - CuAssertIntEquals(tc, ENOMATERIALS, build_building(u, btype, 0, 4, 0)); + u->orders = create_order(K_MAKE, u->faction->locale, 0); + CuAssertIntEquals(tc, ENOMATERIALS, build_building(u, btype, 0, 4, u->orders)); CuAssertPtrEquals(tc, 0, u->region->buildings); CuAssertPtrEquals(tc, 0, u->building); test_cleanup(); @@ -222,7 +223,8 @@ static void test_build_building_with_golem(CuTest *tc) { assert(btype->construction); set_level(bf.u, SK_BUILDING, 1); - CuAssertIntEquals(tc, 1, build_building(u, btype, 0, 1, 0)); + u->orders = create_order(K_MAKE, u->faction->locale, 0); + CuAssertIntEquals(tc, 1, build_building(u, btype, 0, 1, u->orders)); CuAssertPtrNotNull(tc, u->region->buildings); CuAssertIntEquals(tc, 1, u->region->buildings->size); CuAssertIntEquals(tc, 0, u->number); @@ -245,7 +247,8 @@ static void test_build_building_success(CuTest *tc) { i_change(&bf.u->items, rtype->itype, 1); set_level(u, SK_BUILDING, 1); - CuAssertIntEquals(tc, 1, build_building(u, btype, 0, 4, 0)); + u->orders = create_order(K_MAKE, u->faction->locale, 0); + CuAssertIntEquals(tc, 1, build_building(u, btype, 0, 4, u->orders)); CuAssertPtrNotNull(tc, u->region->buildings); CuAssertPtrEquals(tc, u->region->buildings, u->building); CuAssertIntEquals(tc, 1, u->building->size); diff --git a/src/kernel/config.c b/src/kernel/config.c index 2e0f2c32c..9c26ad85a 100644 --- a/src/kernel/config.c +++ b/src/kernel/config.c @@ -530,6 +530,8 @@ int alliedunit(const unit * u, const faction * f2, int mode) ally *sf; int automode; + assert(u); + assert(f2); assert(u->region); /* the unit should be in a region, but it's possible that u->number==0 (TEMP units) */ if (u->faction == f2) return mode; @@ -686,7 +688,7 @@ param_t findparam(const char *s, const struct locale * lang) if (str && *str) { int i; - const void * match; + void * match; void **tokens = get_translations(lang, UT_PARAMS); critbit_tree *cb = (critbit_tree *)*tokens; if (!cb) { @@ -853,7 +855,7 @@ int forbiddenid(int id) ++len; forbid = calloc(len, sizeof(int)); for (i = 0; i != len; ++i) { - forbid[i] = strtol(forbidden[i], NULL, 36); + forbid[i] = atoi36(forbidden[i]); } } for (i = 0; i != len; ++i) @@ -904,11 +906,6 @@ int newcontainerid(void) return random_no; } -bool idle(faction * f) -{ - return (bool)(f ? false : true); -} - int maxworkingpeasants(const struct region *r) { int size = production(r); @@ -922,6 +919,10 @@ static const char * parameter_key(int i) return parameters[i]; } +void init_parameters(struct locale *lang) { + init_translations(lang, UT_PARAMS, parameter_key, MAXPARAMS); +} + void init_terrains_translation(const struct locale *lang) { void **tokens; @@ -991,7 +992,7 @@ void init_locale(struct locale *lang) addtoken(tokens, name, var); } else { - log_error("no translation for magic school %s in locale %s", tok, locale_name(lang)); + log_warning("no translation for magic school %s in locale %s", tok, locale_name(lang)); } tok = strtok(NULL, " "); } @@ -1012,7 +1013,7 @@ void init_locale(struct locale *lang) if (name) addtoken(tokens, name, var); } - init_translations(lang, UT_PARAMS, parameter_key, MAXPARAMS); + init_parameters(lang); init_options_translation(lang); init_terrains_translation(lang); @@ -1199,7 +1200,7 @@ void setguard(unit * u, unsigned int flags) } fset(u, UFL_GUARD); fset(u->region, RF_GUARDED); - if ((int)flags == guard_flags(u)) { + if (flags == guard_flags(u)) { if (a) a_remove(&u->attribs, a); } @@ -1684,6 +1685,11 @@ void kernel_init(void) } static order * defaults[MAXLOCALES]; +keyword_t default_keyword = NOKEYWORD; + +void set_default_order(int kwd) { + default_keyword = (keyword_t)kwd; +} order *default_order(const struct locale *lang) { @@ -1691,6 +1697,11 @@ order *default_order(const struct locale *lang) int i = locale_index(lang); order *result = 0; assert(i < MAXLOCALES); + + if (default_keyword!=NOKEYWORD) { + return create_order(default_keyword, lang, 0); + } + result = defaults[i]; if (!result && usedefault) { const char * str = LOC(lang, "defaultorder"); diff --git a/src/kernel/config.h b/src/kernel/config.h index a10186e6d..056de8f84 100644 --- a/src/kernel/config.h +++ b/src/kernel/config.h @@ -81,12 +81,10 @@ extern "C" { #define ORDERSIZE (DISPLAYSIZE*2) /* max. length of an order */ #define NAMESIZE 128 /* max. Lnge eines Namens, incl trailing 0 */ #define IDSIZE 16 /* max. Lnge einer no (als String), incl trailing 0 */ -#define KEYWORDSIZE 16 /* max. Lnge eines Keyword, incl trailing 0 */ #define OBJECTIDSIZE (NAMESIZE+5+IDSIZE) /* max. Lnge der Strings, die * von struct unitname, etc. zurckgegeben werden. ohne die 0 */ #define BAGCAPACITY 20000 /* soviel pat in einen Bag of Holding */ -#define STRENGTHMULTIPLIER 50 /* multiplier for trollbelt */ /* ----------------- Befehle ----------------------------------- */ @@ -181,7 +179,6 @@ extern "C" { bool has_limited_skills(const struct unit *u); const struct race *findrace(const char *, const struct locale *); - bool idle(struct faction *f); bool unit_has_cursed_item(const struct unit *u); /* grammatik-flags: */ @@ -289,8 +286,12 @@ extern "C" { int AllianceAuto(void); /* flags that allied factions get automatically */ int AllianceRestricted(void); /* flags restricted to allied factions */ int HelpMask(void); /* flags restricted to allied factions */ + struct order *default_order(const struct locale *lang); + void set_default_order(int kwd); + int entertainmoney(const struct region *r); + void init_parameters(struct locale *lang); void free_gamedata(void); diff --git a/src/kernel/curse.c b/src/kernel/curse.c index 27188e2ce..f2e99778f 100644 --- a/src/kernel/curse.c +++ b/src/kernel/curse.c @@ -117,6 +117,8 @@ int curse_age(attrib * a) curse *c = (curse *)a->data.v; int result = 0; + c_clearflag(c, CURSE_ISNEW); + if (c_flags(c) & CURSE_NOAGE) { c->duration = INT_MAX; } @@ -221,7 +223,9 @@ int curse_read(attrib * a, void *owner, struct storage *store) return AT_READ_FAIL; } c->flags = flags; - c_clearflag(c, CURSE_ISNEW); + if (global.data_version < EXPLICIT_CURSE_ISNEW_VERSION) { + c_clearflag(c, CURSE_ISNEW); + } if (c->type->read) c->type->read(store, c, owner); @@ -248,7 +252,12 @@ void curse_write(const attrib * a, const void *owner, struct storage *store) unit *mage = (c->magician && c->magician->number) ? c->magician : NULL; /* copied from c_clearflag */ - flags = (c->flags & ~CURSE_ISNEW) | (c->type->flags & CURSE_ISNEW); + if (global.data_version < EXPLICIT_CURSE_ISNEW_VERSION) { + flags = (c->flags & ~CURSE_ISNEW) | (c->type->flags & CURSE_ISNEW); + } + else { + flags = c->flags | c->type->flags; + } WRITE_INT(store, c->no); WRITE_TOK(store, ct->cname); @@ -298,24 +307,42 @@ const curse_type *ct_find(const char *c) { unsigned int hash = tolower(c[0]); quicklist *ctl = cursetypes[hash]; - int qi; - for (qi = 0; ctl; ql_advance(&ctl, &qi, 1)) { - curse_type *type = (curse_type *)ql_get(ctl, qi); + if (ctl) { + size_t c_len = strlen(c); + int qi; - if (strcmp(c, type->cname) == 0) { - return type; - } - else { - size_t k = _min(strlen(c), strlen(type->cname)); - if (!_memicmp(c, type->cname, k)) { + for (qi = 0; ctl; ql_advance(&ctl, &qi, 1)) { + curse_type *type = (curse_type *)ql_get(ctl, qi); + + if (strcmp(c, type->cname) == 0) { return type; } + else { + size_t k = _min(c_len, strlen(type->cname)); + if (!_memicmp(c, type->cname, k)) { + return type; + } + } } } return NULL; } +void ct_checknames(void) { + int i, qi; + quicklist *ctl; + + for (i = 0; i < 256; ++i) { + ctl = cursetypes[i]; + for (qi = 0; ctl; ql_advance(&ctl, &qi, 1)) { + curse_type *type = (curse_type *)ql_get(ctl, qi); + curse_name(type, default_locale); + + } + } +} + /* ------------------------------------------------------------- */ /* get_curse identifiziert eine Verzauberung ber die ID und gibt * einen pointer auf die struct zurck. @@ -369,15 +396,13 @@ bool remove_curse(attrib ** ap, const curse * c) /* gibt die allgemeine Strke der Verzauberung zurck. id2 wird wie * oben benutzt. Dies ist nicht die Wirkung, sondern die Kraft und * damit der gegen Antimagie wirkende Widerstand einer Verzauberung */ -static float get_cursevigour(const curse * c) +static double get_cursevigour(const curse * c) { - if (c) - return c->vigour; - return 0; + return c ? c->vigour : 0; } /* setzt die Strke der Verzauberung auf i */ -static void set_cursevigour(curse * c, float vigour) +static void set_cursevigour(curse * c, double vigour) { assert(c && vigour > 0); c->vigour = vigour; @@ -387,7 +412,7 @@ static void set_cursevigour(curse * c, float vigour) * Strke zurck. Sollte die Zauberstrke unter Null sinken, lst er * sich auf. */ -float curse_changevigour(attrib ** ap, curse * c, float vigour) +double curse_changevigour(attrib ** ap, curse * c, double vigour) { vigour += get_cursevigour(c); @@ -403,7 +428,7 @@ float curse_changevigour(attrib ** ap, curse * c, float vigour) /* ------------------------------------------------------------- */ -float curse_geteffect(const curse * c) +double curse_geteffect(const curse * c) { if (c == NULL) return 0; @@ -414,7 +439,7 @@ float curse_geteffect(const curse * c) int curse_geteffect_int(const curse * c) { - float effect = curse_geteffect(c); + double effect = curse_geteffect(c); if (effect - (int)effect != 0) { log_error("curse has an integer attribute with float value: '%s' = %lf", c->type->cname, effect); @@ -468,7 +493,7 @@ static void set_cursedmen(curse * c, int cursedmen) * dieses Typs geben, gibt es den bestehenden zurck. */ static curse *make_curse(unit * mage, attrib ** ap, const curse_type * ct, - float vigour, int duration, float effect, int men) + double vigour, int duration, double effect, int men) { curse *c; attrib *a; @@ -492,12 +517,9 @@ static curse *make_curse(unit * mage, attrib ** ap, const curse_type * ct, break; case CURSETYP_UNIT: - { c->data.i = men; break; } - - } return c; } @@ -505,7 +527,7 @@ static curse *make_curse(unit * mage, attrib ** ap, const curse_type * ct, * passenden Typ verzweigt und die relevanten Variablen weitergegeben. */ curse *create_curse(unit * magician, attrib ** ap, const curse_type * ct, - float vigour, int duration, float effect, int men) + double vigour, int duration, double effect, int men) { curse *c; @@ -720,13 +742,7 @@ static const char *oldnames[MAXCURSE] = { "speed", "orcish", "magicboost", - "insectfur", - "strength", - "worse", - "magicresistance", - "itemcloak", - "sparkle", - "skillmod" + "insectfur" }; const char *oldcursename(int id) @@ -762,7 +778,7 @@ message *cinfo_simple(const void *obj, objtype_t typ, const struct curse * c, * die Kraft des Curse um die halbe Strke der Antimagie reduziert. * Zurckgegeben wird der noch unverbrauchte Rest von force. */ -float destr_curse(curse * c, int cast_level, float force) +double destr_curse(curse * c, int cast_level, double force) { if (cast_level < c->vigour) { /* Zauber ist nicht stark genug */ double probability = 0.1 + (cast_level - c->vigour) * 0.2; @@ -770,7 +786,7 @@ float destr_curse(curse * c, int cast_level, float force) if (chance(probability)) { force -= c->vigour; if (c->type->change_vigour) { - c->type->change_vigour(c, -((float)cast_level + 1) / 2); + c->type->change_vigour(c, -(cast_level + 1) / 2); } else { c->vigour -= cast_level + 1 / 2; diff --git a/src/kernel/curse.h b/src/kernel/curse.h index b98b8601c..cd745bfdb 100644 --- a/src/kernel/curse.h +++ b/src/kernel/curse.h @@ -26,6 +26,9 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. extern "C" { #endif + struct curse; + struct curse_type; + /* Sprueche in der struct region und auf Einheiten, Schiffen oder Burgen * (struct attribute) */ @@ -98,7 +101,6 @@ extern "C" { */ enum { - /* struct's vom typ curse: */ C_FOGTRAP, C_ANTIMAGICZONE, C_FARVISION, @@ -128,18 +130,10 @@ extern "C" { C_RIOT, /*region in Aufruhr */ C_NOCOST, C_CURSED_BY_THE_GODS, - /* struct's vom untertyp curse_unit: */ C_SPEED, /* Beschleunigt */ C_ORC, C_MBOOST, C_KAELTESCHUTZ, - C_STRENGTH, - C_ALLSKILLS, - C_MAGICRESISTANCE, /* 44 - verndert Magieresistenz */ - C_ITEMCLOAK, - C_SPARKLE, - /* struct's vom untertyp curse_skill: */ - C_SKILL, MAXCURSE /* OBS: when removing curses, remember to update read_ccompat() */ }; @@ -188,18 +182,6 @@ extern "C" { /* ------------------------------------------------------------- */ /* Allgemeine Zauberwirkungen */ - typedef struct curse { - struct curse *nexthash; - int no; /* 'Einheitennummer' dieses Curse */ - const struct curse_type *type; /* Zeiger auf ein curse_type-struct */ - int flags; /* WARNING: these are XORed with type->flags! */ - int duration; /* Dauer der Verzauberung. Wird jede Runde vermindert */ - float vigour; /* Strke der Verzauberung, Widerstand gegen Antimagie */ - struct unit *magician; /* Pointer auf den Magier, der den Spruch gewirkt hat */ - float effect; - variant data; /* pointer auf spezielle curse-unterstructs */ - } curse; - #define c_flags(c) ((c)->type->flags ^ (c)->flags) /* ------------------------------------------------------------- */ @@ -209,17 +191,29 @@ extern "C" { int typ; int flags; int mergeflags; - struct message *(*curseinfo) (const void *, objtype_t, const struct curse *, - int); - void(*change_vigour) (curse *, float); - int(*read) (struct storage * store, curse * c, void *target); - int(*write) (struct storage * store, const struct curse * c, + struct message *(*curseinfo) (const void *, objtype_t, + const struct curse *, int); + void(*change_vigour) (struct curse *, double); + int(*read) (struct storage * store, struct curse *, void *target); + int(*write) (struct storage * store, const struct curse *, const void *target); int(*cansee) (const struct faction *, const void *, objtype_t, const struct curse *, int); - int(*age) (curse *); + int(*age) (struct curse *); } curse_type; + typedef struct curse { + variant data; /* pointer auf spezielle curse-unterstructs */ + struct curse *nexthash; + const curse_type *type; /* Zeiger auf ein curse_type-struct */ + struct unit *magician; /* Pointer auf den Magier, der den Spruch gewirkt hat */ + double vigour; /* Strke der Verzauberung, Widerstand gegen Antimagie */ + double effect; + int no; /* 'Einheitennummer' dieses Curse */ + int flags; /* WARNING: these are XORed with type->flags! */ + int duration; /* Dauer der Verzauberung. Wird jede Runde vermindert */ + } curse; + extern struct attrib_type at_curse; void curse_write(const struct attrib *a, const void *owner, struct storage *store); @@ -238,7 +232,7 @@ extern "C" { */ curse *create_curse(struct unit *magician, struct attrib **ap, - const curse_type * ctype, float vigour, int duration, float ceffect, + const curse_type * ctype, double vigour, int duration, double ceffect, int men); /* Verzweigt automatisch zum passenden struct-typ. Sollte es schon * einen Zauber dieses Typs geben, so wird der neue dazuaddiert. Die @@ -248,47 +242,46 @@ extern "C" { void destroy_curse(curse * c); - bool is_cursed_internal(struct attrib *ap, const curse_type * ctype); /* ignoriert CURSE_ISNEW */ + bool is_cursed_internal(struct attrib *ap, const curse_type * ctype); + /* lscht einen konkreten Spruch auf einem Objekt. */ bool remove_curse(struct attrib **ap, const struct curse *c); - /* lscht einen konkreten Spruch auf einem Objekt. - */ - int curse_geteffect_int(const struct curse *c); - float curse_geteffect(const struct curse *c); /* gibt die Auswirkungen der Verzauberungen zurck. zB bei * Skillmodifiziernden Verzauberungen ist hier der Modifizierer * gespeichert. Wird automatisch beim Anlegen eines neuen curse * gesetzt. Gibt immer den ersten Treffer von ap aus zurck. */ + int curse_geteffect_int(const struct curse *c); + double curse_geteffect(const struct curse *c); - float curse_changevigour(struct attrib **ap, curse * c, float i); /* verndert die Strke der Verzauberung um i */ + double curse_changevigour(struct attrib **ap, curse * c, double delta); - int get_cursedmen(struct unit *u, const struct curse *c); /* gibt bei Personenbeschrnkten Verzauberungen die Anzahl der * betroffenen Personen zurck. Ansonsten wird 0 zurckgegeben. */ + int get_cursedmen(struct unit *u, const struct curse *c); + /* setzt/loescht Spezialflag einer Verzauberung (zB 'dauert ewig') */ void c_setflag(curse * c, unsigned int flag); void c_clearflag(curse * c, unsigned int flags); - /* setzt/loescht Spezialflag einer Verzauberung (zB 'dauert ewig') */ - void transfer_curse(struct unit *u, struct unit *u2, int n); /* sorgt dafr, das bei der bergabe von Personen die curse-attribute * korrekt gehandhabt werden. Je nach internen Flag kann dies * unterschiedlich gewnscht sein * */ + void transfer_curse(struct unit *u, struct unit *u2, int n); - struct curse *get_curse(struct attrib *ap, const curse_type * ctype); /* gibt pointer auf die erste curse-struct zurck, deren Typ ctype ist, * oder einen NULL-pointer * */ + struct curse *get_curse(struct attrib *ap, const curse_type * ctype); int find_cursebyname(const char *c); const curse_type *ct_find(const char *c); void ct_register(const curse_type *); - /* Regionszauber */ + void ct_checknames(void); curse *cfindhash(int i); @@ -298,13 +291,13 @@ extern "C" { void curse_done(struct attrib *a); int curse_age(struct attrib *a); - float destr_curse(struct curse *c, int cast_level, float force); + double destr_curse(struct curse *c, int cast_level, double force); int resolve_curse(variant data, void *address); bool is_cursed_with(const struct attrib *ap, const struct curse *c); - bool curse_active(const struct curse *c); /* gibt true, wenn der Curse nicht NULL oder inaktiv ist */ + bool curse_active(const struct curse *c); /*** COMPATIBILITY MACROS. DO NOT USE FOR NEW CODE, REPLACE IN OLD CODE: */ const char *oldcursename(int id); diff --git a/src/kernel/curse.test.c b/src/kernel/curse.test.c index 577d6551a..7f8bb4db2 100644 --- a/src/kernel/curse.test.c +++ b/src/kernel/curse.test.c @@ -1,15 +1,27 @@ #include -#include "types.h" -#include "curse.h" +#include #include #include +#include #include #include +#include +#include +#include +#include +#include #include +#include "curse.h" + +#include +#include +#include + #include + static void test_curse(CuTest * tc) { attrib *attrs = NULL; @@ -83,6 +95,58 @@ static void test_bad_dreams(CuTest *tc) { test_cleanup(); } +static void test_memstream(CuTest *tc) { + storage store; + stream out = { 0 }; + char buf[1024]; + int val=0; + + mstream_init(&out); + binstore_init(&store, &out); + store.handle.data = &out; + + WRITE_INT(&store, 999999); + WRITE_TOK(&store, "fortytwo"); + WRITE_INT(&store, 42); + + out.api->rewind(out.handle); + READ_INT(&store, &val); + READ_TOK(&store, buf, 1024); + CuAssertIntEquals(tc, 999999, val); + CuAssertStrEquals(tc, "fortytwo", buf); + READ_INT(&store, &val); + CuAssertIntEquals(tc, 42, val); + mstream_done(&out); +} + +static void test_write_flag(CuTest *tc) { + curse_fixture fix; + storage store; + char buf[1024]; + stream out = { 0 }; + size_t len; + + mstream_init(&out); + binstore_init(&store, &out); + store.handle.data = &out; + + setup_curse(&fix, "gbdream"); + fix.c->flags = 42 | CURSE_ISNEW; + curse_write(fix.r->attribs, fix.r, &store); + out.api->rewind(out.handle); + len = out.api->read(out.handle, buf, sizeof(buf)); + buf[len] = '\0'; + out.api->rewind(out.handle); + curse_read(fix.r->attribs, fix.r, &store); + CuAssertIntEquals(tc, 42 | CURSE_ISNEW, ((curse *) fix.r->attribs->data.v)->flags); + global.data_version = RELEASE_VERSION; + CuAssertIntEquals(tc, RELEASE_VERSION, global.data_version); + + mstream_done(&out); + binstore_done(&store); + test_cleanup(); +} + CuSuite *get_curse_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -91,5 +155,7 @@ CuSuite *get_curse_suite(void) SUITE_ADD_TEST(suite, test_magicstreet_warning); SUITE_ADD_TEST(suite, test_good_dreams); SUITE_ADD_TEST(suite, test_bad_dreams); + SUITE_ADD_TEST(suite, test_memstream); + SUITE_ADD_TEST(suite, test_write_flag); return suite; } diff --git a/src/kernel/equipment.c b/src/kernel/equipment.c index e426f8e0f..1511e2865 100644 --- a/src/kernel/equipment.c +++ b/src/kernel/equipment.c @@ -174,7 +174,7 @@ void equip_unit_mask(struct unit *u, const struct equipment *eq, int mask) int i; for (i = 0; eq->subsets[i].sets; ++i) { if (chance(eq->subsets[i].chance)) { - float rnd = (1 + rng_int() % 1000) / 1000.0f; + double rnd = (1 + rng_int() % 1000) / 1000.0; int k; for (k = 0; eq->subsets[i].sets[k].set; ++k) { if (rnd <= eq->subsets[i].sets[k].chance) { @@ -209,7 +209,7 @@ void equip_items(struct item **items, const struct equipment *eq) int i; for (i = 0; eq->subsets[i].sets; ++i) { if (chance(eq->subsets[i].chance)) { - float rnd = (1 + rng_int() % 1000) / 1000.0f; + double rnd = (1 + rng_int() % 1000) / 1000.0; int k; for (k = 0; eq->subsets[i].sets[k].set; ++k) { if (rnd <= eq->subsets[i].sets[k].chance) { diff --git a/src/kernel/faction.c b/src/kernel/faction.c index 139f0e06c..41236840d 100755 --- a/src/kernel/faction.c +++ b/src/kernel/faction.c @@ -257,7 +257,7 @@ unit *addplayer(region * r, faction * f) char buffer[32]; assert(f->units == NULL); - set_ursprung(f, 0, r->x, r->y); + faction_setorigin(f, 0, r->x, r->y); u = create_unit(r, f, 1, f->race, 0, NULL, NULL); equip_items(&u->faction->items, get_equipment("new_faction")); equip_unit(u, get_equipment("first_unit")); @@ -651,9 +651,47 @@ void remove_empty_factions(void) *fp = f->next; funhash(f); free_faction(f); + if (f->alliance && f->alliance->_leader == f) { + setalliance(f, 0); + } free(f); } else fp = &(*fp)->next; } } + +void faction_getorigin(const faction * f, int id, int *x, int *y) +{ + ursprung *ur; + + assert(f && x && y); + for (ur = f->ursprung; ur; ur = ur->next) { + if (ur->id == id) { + *x = ur->x; + *y = ur->y; + break; + } + } +} + +void faction_setorigin(faction * f, int id, int x, int y) +{ + ursprung *ur; + assert(f != NULL); + for (ur = f->ursprung; ur; ur = ur->next) { + if (ur->id == id) { + ur->x = ur->x + x; + ur->y = ur->y + y; + return; + } + } + + ur = calloc(1, sizeof(ursprung)); + ur->id = id; + ur->x = x; + ur->y = y; + + addlist(&f->ursprung, ur); +} + diff --git a/src/kernel/faction.h b/src/kernel/faction.h index a9482bedd..db8ce4389 100644 --- a/src/kernel/faction.h +++ b/src/kernel/faction.h @@ -154,6 +154,9 @@ extern "C" { void faction_setpassword(struct faction *self, const char *password); bool valid_race(const struct faction *f, const struct race *rc); + void faction_getorigin(const struct faction * f, int id, int *x, int *y); + void faction_setorigin(struct faction * f, int id, int x, int y); + struct spellbook * faction_get_spellbook(struct faction *f); /* skills */ diff --git a/src/kernel/faction.test.c b/src/kernel/faction.test.c index b0d0d2ee2..d1a5c53be 100644 --- a/src/kernel/faction.test.c +++ b/src/kernel/faction.test.c @@ -1,9 +1,11 @@ #include #include +#include #include #include #include +#include #include #include @@ -29,6 +31,20 @@ static void test_remove_empty_factions_allies(CuTest *tc) { test_cleanup(); } +static void test_remove_empty_factions_alliance(CuTest *tc) { + faction *f; + struct alliance *al; + + test_cleanup(); + f = test_create_faction(0); + al = makealliance(0, "Hodor"); + setalliance(f, al); + CuAssertPtrEquals(tc, f, alliance_get_leader(al)); + remove_empty_factions(); + CuAssertPtrEquals(tc, 0, al->_leader); + test_cleanup(); +} + static void test_remove_empty_factions(CuTest *tc) { faction *f, *fm; int fno; @@ -70,9 +86,12 @@ static void test_remove_dead_factions(CuTest *tc) { static void test_addfaction(CuTest *tc) { faction *f = 0; - const struct race *rc = rc_get_or_create("human"); - const struct locale *lang = get_or_create_locale("en"); + const struct race *rc; + const struct locale *lang; + test_cleanup(); + rc = rc_get_or_create("human"); + lang = get_or_create_locale("en"); f = addfaction("test@eressea.de", "hurrdurr", rc, lang, 1234); CuAssertPtrNotNull(tc, f); CuAssertPtrNotNull(tc, f->name); @@ -106,13 +125,60 @@ static void test_get_monsters(CuTest *tc) { test_cleanup(); } +static void test_set_origin(CuTest *tc) { + faction *f; + int x = 0, y = 0; + plane *pl; + + test_cleanup(); + test_create_world(); + pl = create_new_plane(0, "", 0, 19, 0, 19, 0); + f = test_create_faction(0); + CuAssertPtrEquals(tc, 0, f->ursprung); + faction_setorigin(f, 0, 1, 1); + CuAssertIntEquals(tc, 0, f->ursprung->id); + CuAssertIntEquals(tc, 1, f->ursprung->x); + CuAssertIntEquals(tc, 1, f->ursprung->y); + faction_getorigin(f, 0, &x, &y); + CuAssertIntEquals(tc, 1, x); + CuAssertIntEquals(tc, 1, y); + adjust_coordinates(f, &x, &y, pl); + CuAssertIntEquals(tc, -9, x); + CuAssertIntEquals(tc, -9, y); + adjust_coordinates(f, &x, &y, 0); + CuAssertIntEquals(tc, -10, x); + CuAssertIntEquals(tc, -10, y); + test_cleanup(); +} + +static void test_set_origin_bug(CuTest *tc) { + faction *f; + plane *pl; + int x = 17, y = 10; + + test_cleanup(); + test_create_world(); + pl = create_new_plane(0, "", 0, 19, 0, 19, 0); + f = test_create_faction(0); + faction_setorigin(f, 0, -10, 3); + faction_setorigin(f, 0, -13, -4); + adjust_coordinates(f, &x, &y, pl); + CuAssertIntEquals(tc, 0, f->ursprung->id); + CuAssertIntEquals(tc, -9, x); + CuAssertIntEquals(tc, 2, y); + test_cleanup(); +} + CuSuite *get_faction_suite(void) { CuSuite *suite = CuSuiteNew(); SUITE_ADD_TEST(suite, test_addfaction); SUITE_ADD_TEST(suite, test_remove_empty_factions); SUITE_ADD_TEST(suite, test_remove_empty_factions_allies); + SUITE_ADD_TEST(suite, test_remove_empty_factions_alliance); SUITE_ADD_TEST(suite, test_remove_dead_factions); SUITE_ADD_TEST(suite, test_get_monsters); + SUITE_ADD_TEST(suite, test_set_origin); + SUITE_ADD_TEST(suite, test_set_origin_bug); return suite; } diff --git a/src/kernel/item.c b/src/kernel/item.c index 229fd3568..ea7e33dd5 100644 --- a/src/kernel/item.c +++ b/src/kernel/item.c @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 1998-2015, Enno Rehling Katja Zedel @@ -332,10 +332,15 @@ potion_type *new_potiontype(item_type * itype, int level) } void it_set_appearance(item_type *itype, const char *appearance) { - assert(itype && itype->rtype); - itype->_appearance[0] = _strdup(appearance); - itype->_appearance[1] = appearance ? - strcat(strcpy((char *)malloc(strlen((char *)appearance) + 3), (char *)appearance), "_p") : 0; + assert(itype); + assert(itype->rtype); + if (appearance) { + itype->_appearance[0] = _strdup(appearance); + itype->_appearance[1] = strcat(strcpy((char *)malloc(strlen((char *)appearance) + 3), (char *)appearance), "_p"); + } else { + itype->_appearance[0] = 0; + itype->_appearance[1] = 0; + } } const resource_type *item2resource(const item_type * itype) @@ -379,7 +384,7 @@ const potion_type *resource2potion(const resource_type * rtype) resource_type *rt_find(const char *name) { - const void * matches; + void * matches; resource_type *result = 0; if (cb_find_prefix(&cb_resources, name, strlen(name) + 1, &matches, 1, 0)) { @@ -1064,7 +1069,7 @@ const resource_type *findresourcetype(const char *name, const struct locale *lan char buffer[128]; if (transliterate(buffer, sizeof(buffer), name)) { - const void * match; + void * match; if (!cb->root) { /* first-time initialization of resource names for this locale */ cb_foreach(&cb_resources, "", 0, add_resourcename_cb, (void *)lang); @@ -1117,7 +1122,7 @@ const item_type *finditemtype(const char *name, const struct locale *lang) assert(name); if (transliterate(buffer, sizeof(buffer), name)) { - const void * match; + void * match; if (!cb->root) { /* first-time initialization of item names for this locale */ cb_foreach(&cb_resources, "", 0, add_itemname_cb, (void *)lang); diff --git a/src/kernel/jsonconf.c b/src/kernel/jsonconf.c index 1b6995778..8db61376c 100644 --- a/src/kernel/jsonconf.c +++ b/src/kernel/jsonconf.c @@ -62,6 +62,7 @@ static int json_flags(cJSON *json, const char *flags[]) { for (i = 0; flags[i]; ++i) { if (strcmp(flags[i], entry->valuestring) == 0) { result |= (1 << i); + break; } } } @@ -344,7 +345,7 @@ static void json_race(cJSON *json, race *rc) { "coastal", "", "cansail", 0 }; const char *ecflags[] = { - "", "giveitem", "giveperson", + "", "keepitem", "giveperson", "giveunit", "getitem", 0 }; if (json->type != cJSON_Object) { diff --git a/src/kernel/jsonconf.test.c b/src/kernel/jsonconf.test.c index db861fcfc..bbe222fb6 100644 --- a/src/kernel/jsonconf.test.c +++ b/src/kernel/jsonconf.test.c @@ -51,7 +51,7 @@ static void test_flags(CuTest *tc) { check_flag(tc, "dragon", RCF_DRAGON); check_flag(tc, "fly", RCF_FLY); check_ec_flag(tc, "getitem", GETITEM); - check_ec_flag(tc, "giveitem", GIVEITEM); + check_ec_flag(tc, "keepitem", ECF_KEEP_ITEM); check_ec_flag(tc, "giveperson", GIVEPERSON); check_ec_flag(tc, "giveunit", GIVEUNIT); test_cleanup(); diff --git a/src/kernel/messages.c b/src/kernel/messages.c index f92b8acf9..28625ff85 100644 --- a/src/kernel/messages.c +++ b/src/kernel/messages.c @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 1998-2015, Enno Rehling Katja Zedel @@ -147,6 +147,7 @@ message *msg_message(const char *name, const char *sig, ...) const message_type *mtype = mt_find(name); char paramname[64]; const char *ic = sig; + int argnum=0; variant args[16]; memset(args, 0, sizeof(args)); @@ -183,15 +184,18 @@ message *msg_message(const char *name, const char *sig, ...) else { assert(!"unknown variant type"); } + argnum++; } else { log_error("invalid parameter %s for message type %s\n", paramname, mtype->name); - assert(!"program aborted."); } while (*ic && !isalnum(*ic)) ic++; } va_end(vargs); + if (argnum != mtype->nparameters) { + log_error("not enough parameters for message type %s\n", mtype->name); + } return msg_create(mtype, args); } @@ -201,12 +205,6 @@ caddmessage(region * r, faction * f, const char *s, msg_t mtype, int level) { message *m = NULL; -#define LOG_ENGLISH -#ifdef LOG_ENGLISH - if (f && f->locale != default_locale) { - log_warning("message for locale \"%s\": %s\n", locale_name(f->locale), s); - } -#endif unused_arg(level); switch (mtype) { case MSG_INCOME: @@ -276,12 +274,20 @@ message * cmistake(const unit * u, struct order *ord, int mno, int mtype) return result; } +void syntax_error(const struct unit *u, struct order *ord) +{ + message * result; + result = msg_error(u, ord, 10); + ADDMSG(&u->faction->msgs, result); +} + extern unsigned int new_hashstring(const char *s); void free_messagelist(message_list * msgs) { - struct mlist **mlistptr = &msgs->begin; - while (*mlistptr) { + struct mlist **mlistptr; + assert(msgs && msgs->begin); + for (mlistptr = &msgs->begin; *mlistptr;) { struct mlist *ml = *mlistptr; *mlistptr = ml->next; msg_release(ml->msg); @@ -292,6 +298,7 @@ void free_messagelist(message_list * msgs) message *add_message(message_list ** pm, message * m) { + assert(m && m->type); if (!lomem && m != NULL) { struct mlist *mnew = malloc(sizeof(struct mlist)); if (*pm == NULL) { diff --git a/src/kernel/messages.h b/src/kernel/messages.h index c03dca1b7..4ce412bcd 100644 --- a/src/kernel/messages.h +++ b/src/kernel/messages.h @@ -56,6 +56,7 @@ extern "C" { #define ADDMSG(msgs, mcreate) { message * m = mcreate; if (m) { assert(m->refcount>=1); add_message(msgs, m); msg_release(m); } } + void syntax_error(const struct unit *u, struct order *ord); struct message * cmistake(const struct unit *u, struct order *ord, int mno, int mtype); struct message * msg_error(const struct unit * u, struct order *ord, int mno); #ifdef __cplusplus diff --git a/src/kernel/order.c b/src/kernel/order.c index 70114125d..008bfe0fe 100644 --- a/src/kernel/order.c +++ b/src/kernel/order.c @@ -65,6 +65,9 @@ static void release_data(order_data * data) void replace_order(order ** dlist, order * orig, const order * src) { + assert(src); + assert(orig); + assert(dlist); while (*dlist != NULL) { order *dst = *dlist; if (dst->data == orig->data) { @@ -249,7 +252,20 @@ static order_data *create_data(keyword_t kwd, const char *sptr, int lindex) return data; } -static order *create_order_i(keyword_t kwd, const char *sptr, int persistent, +static void free_localedata(int lindex) { + int i; + for (i = 0; i != MAXKEYWORDS; ++i) { + release_data(locale_array[lindex]->short_orders[i]); + locale_array[lindex]->short_orders[i] = 0; + } + for (i = 0; i != MAXSKILLS; ++i) { + release_data(locale_array[lindex]->study_orders[i]); + locale_array[lindex]->study_orders[i] = 0; + } + locale_array[lindex]->lang = 0; +} + +static order *create_order_i(keyword_t kwd, const char *sptr, bool persistent, const struct locale *lang) { order *ord = NULL; @@ -273,7 +289,12 @@ static order *create_order_i(keyword_t kwd, const char *sptr, int persistent, lindex = locale_index(lang); assert(lindex < MAXLOCALES); - locale_array[lindex] = (locale_data *)calloc(1, sizeof(locale_data)); + if (!locale_array[lindex]) { + locale_array[lindex] = (locale_data *)calloc(1, sizeof(locale_data)); + } + else if (locale_array[lindex]->lang != lang) { + free_localedata(lindex); + } locale_array[lindex]->lang = lang; ord = (order *)malloc(sizeof(order)); @@ -289,13 +310,13 @@ order *create_order(keyword_t kwd, const struct locale * lang, const char *params, ...) { char zBuffer[DISPLAYSIZE]; - assert(lang); if (params) { char *bufp = zBuffer; int bytes; size_t size = sizeof(zBuffer) - 1; va_list marker; + assert(lang); va_start(marker, params); while (*params) { if (*params == '%') { @@ -305,6 +326,7 @@ order *create_order(keyword_t kwd, const struct locale * lang, switch (*params) { case 's': s = va_arg(marker, const char *); + assert(s); bytes = (int)strlcpy(bufp, s, size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); @@ -337,7 +359,7 @@ order *create_order(keyword_t kwd, const struct locale * lang, else { zBuffer[0] = 0; } - return create_order_i(kwd, zBuffer, 0, lang); + return create_order_i(kwd, zBuffer, false, lang); } order *parse_order(const char *s, const struct locale * lang) @@ -350,11 +372,11 @@ order *parse_order(const char *s, const struct locale * lang) if (*s != 0) { keyword_t kwd; const char *sptr; - int persistent = 0; + bool persistent = false; const char * p; while (*s == '@') { - persistent = 1; + persistent = true; ++s; } sptr = s; @@ -385,9 +407,8 @@ order *parse_order(const char *s, const struct locale * lang) * \return true if the order is long * \sa is_exclusive(), is_repeated(), is_persistent() */ -bool is_repeated(const order * ord) +bool is_repeated(keyword_t kwd) { - keyword_t kwd = ORD_KEYWORD(ord); switch (kwd) { case K_CAST: case K_BUY: @@ -464,10 +485,8 @@ bool is_exclusive(const order * ord) * \return true if the order is long * \sa is_exclusive(), is_repeated(), is_persistent() */ -bool is_long(const order * ord) +bool is_long(keyword_t kwd) { - keyword_t kwd = ORD_KEYWORD(ord); - switch (kwd) { case K_CAST: case K_BUY: @@ -510,18 +529,15 @@ bool is_long(const order * ord) bool is_persistent(const order * ord) { keyword_t kwd = ORD_KEYWORD(ord); - int persist = ord->_persistent != 0; switch (kwd) { case K_MOVE: case NOKEYWORD: /* lang, aber niemals persistent! */ return false; - case K_KOMMENTAR: return true; - default: - return persist || is_repeated(ord); + return ord->_persistent || is_repeated(kwd); } } diff --git a/src/kernel/order.h b/src/kernel/order.h index 22e401438..75d741e42 100644 --- a/src/kernel/order.h +++ b/src/kernel/order.h @@ -33,7 +33,7 @@ extern "C" { struct order *next; /* do not access this data: */ struct order_data *data; - int _persistent : 1; + bool _persistent; } order; /* constructor */ @@ -55,8 +55,8 @@ extern "C" { char* get_command(const order *ord, char *buffer, size_t size); bool is_persistent(const order * ord); bool is_exclusive(const order * ord); - bool is_repeated(const order * ord); - bool is_long(const order * ord); + bool is_repeated(keyword_t kwd); + bool is_long(keyword_t kwd); char *write_order(const order * ord, char *buffer, size_t size); keyword_t init_order(const struct order *ord); diff --git a/src/kernel/order.test.c b/src/kernel/order.test.c index 414dd87e7..6900da420 100644 --- a/src/kernel/order.test.c +++ b/src/kernel/order.test.c @@ -143,6 +143,21 @@ static void test_skip_token(CuTest *tc) { CuAssertStrEquals(tc, 0, getstrtoken()); } +static void test_replace_order(CuTest *tc) { + order *orders = 0, *orig, *repl; + struct locale * lang = get_or_create_locale("en"); + + orig = create_order(K_MAKE, lang, 0); + repl = create_order(K_ALLY, lang, 0); + replace_order(&orders, orig, repl); + CuAssertPtrEquals(tc, 0, orders); + orders = orig; + replace_order(&orders, orig, repl); + CuAssertPtrNotNull(tc, orders); + CuAssertPtrEquals(tc, 0, orders->next); + CuAssertIntEquals(tc, getkeyword(repl), getkeyword(orders)); +} + CuSuite *get_order_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -152,6 +167,7 @@ CuSuite *get_order_suite(void) SUITE_ADD_TEST(suite, test_parse_make_temp); SUITE_ADD_TEST(suite, test_parse_maketemp); SUITE_ADD_TEST(suite, test_init_order); + SUITE_ADD_TEST(suite, test_replace_order); SUITE_ADD_TEST(suite, test_skip_token); SUITE_ADD_TEST(suite, test_getstrtoken); return suite; diff --git a/src/kernel/plane.c b/src/kernel/plane.c index 6be95f41b..32c95f6a8 100644 --- a/src/kernel/plane.c +++ b/src/kernel/plane.c @@ -136,7 +136,7 @@ ursprung_x(const faction * f, const plane * pl, const region * rdefault) } if (!rdefault) return 0; - set_ursprung((faction *)f, id, rdefault->x - plane_center_x(pl), + faction_setorigin((faction *)f, id, rdefault->x - plane_center_x(pl), rdefault->y - plane_center_y(pl)); return rdefault->x - plane_center_x(pl); } @@ -159,7 +159,7 @@ ursprung_y(const faction * f, const plane * pl, const region * rdefault) } if (!rdefault) return 0; - set_ursprung((faction *)f, id, rdefault->x - plane_center_x(pl), + faction_setorigin((faction *)f, id, rdefault->x - plane_center_x(pl), rdefault->y - plane_center_y(pl)); return rdefault->y - plane_center_y(pl); } @@ -181,14 +181,15 @@ int plane_center_y(const plane * pl) } void -adjust_coordinates(const faction * f, int *x, int *y, const plane * pl, -const region * r) +adjust_coordinates(const faction * f, int *x, int *y, const plane * pl) { int nx = *x; int ny = *y; if (f) { - nx -= ursprung_x(f, pl, r); - ny -= ursprung_y(f, pl, r); + int ux = 0, uy = 0; + faction_getorigin(f, pl?pl->id:0, &ux, &uy); + nx -= ux; + ny -= uy; } if (pl) { int plx = plane_center_x(pl); @@ -198,8 +199,8 @@ const region * r) int width_2 = width / 2; int height_2 = height / 2; - nx -= plx; - ny -= ply; + nx = (nx - plx) % width; + ny = (ny - ply) % height; if (nx < 0) nx = (width - (-nx) % width); @@ -221,26 +222,6 @@ const region * r) *y = ny; } -void set_ursprung(faction * f, int id, int x, int y) -{ - ursprung *ur; - assert(f != NULL); - for (ur = f->ursprung; ur; ur = ur->next) { - if (ur->id == id) { - ur->x = ur->x + x; - ur->y = ur->y + y; - return; - } - } - - ur = calloc(1, sizeof(ursprung)); - ur->id = id; - ur->x = x; - ur->y = y; - - addlist(&f->ursprung, ur); -} - plane *create_new_plane(int id, const char *name, int minx, int maxx, int miny, int maxy, int flags) { diff --git a/src/kernel/plane.h b/src/kernel/plane.h index 3ef387754..2426c6a1a 100644 --- a/src/kernel/plane.h +++ b/src/kernel/plane.h @@ -70,7 +70,6 @@ extern "C" { struct plane *getplanebyid(int id); int plane_center_x(const struct plane *pl); int plane_center_y(const struct plane *pl); - void set_ursprung(struct faction *f, int id, int x, int y); struct plane *create_new_plane(int id, const char *name, int minx, int maxx, int miny, int maxy, int flags); struct plane *getplanebyname(const char *); @@ -82,8 +81,7 @@ extern "C" { extern int read_plane_reference(plane ** pp, struct storage *store); extern int plane_width(const plane * pl); extern int plane_height(const plane * pl); - void adjust_coordinates(const struct faction *f, int *x, int *y, - const struct plane *pl, const struct region *r); + void adjust_coordinates(const struct faction *f, int *x, int *y, const struct plane *pl); #ifdef __cplusplus } #endif diff --git a/src/kernel/pool.c b/src/kernel/pool.c index e487abf23..ab1800556 100644 --- a/src/kernel/pool.c +++ b/src/kernel/pool.c @@ -78,9 +78,6 @@ int change_resource(unit * u, const resource_type * rtype, int change) assert(!"undefined resource detected. rtype->uchange not initialized."); assert(i == get_resource(u, rtype)); assert(i >= 0); - if (i >= 100000000) { - log_warning("%s has %d %s\n", unitname(u), i, rtype->_name); - } return i; } @@ -179,7 +176,7 @@ int count) if (u != v && (v->items || rtype->uget)) { int mask; - if ((urace(v)->ec_flags & GIVEITEM) == 0) + if ((urace(v)->ec_flags & ECF_KEEP_ITEM)) continue; if (v->faction == f) { @@ -232,7 +229,7 @@ use_pooled(unit * u, const resource_type * rtype, unsigned int mode, int count) for (v = r->units; use > 0 && v != NULL; v = v->next) { if (u != v) { int mask; - if ((urace(v)->ec_flags & GIVEITEM) == 0) + if ((urace(v)->ec_flags & ECF_KEEP_ITEM)) continue; if (v->items == NULL && rtype->uget == NULL) continue; diff --git a/src/kernel/race.c b/src/kernel/race.c index f577216db..155a1d326 100644 --- a/src/kernel/race.c +++ b/src/kernel/race.c @@ -158,6 +158,7 @@ static race *rc_find_i(const char *name) } if (!rc && strcmp(name, "uruk") == 0) { rc = rc_find_i("orc"); + log_warning("a reference was made to the retired race '%s', returning '%s'.", name, rc->_name); } return rc; } @@ -169,6 +170,7 @@ const race * rc_find(const char *name) { race *rc_get_or_create(const char *zName) { race *rc; + int i; assert(zName); rc = rc_find_i(zName); @@ -182,6 +184,7 @@ race *rc_get_or_create(const char *zName) rc->recruit_multi = 1.0F; rc->regaura = 1.0F; rc->speed = 1.0F; + rc->battle_flags = BF_CANATTACK; if (strchr(zName, ' ') != NULL) { log_error("race '%s' has an invalid name. remove spaces\n", zName); assert(strchr(zName, ' ') == NULL); @@ -191,7 +194,8 @@ race *rc_get_or_create(const char *zName) rc->precombatspell = NULL; rc->attack[0].type = AT_COMBATSPELL; - rc->attack[1].type = AT_NONE; + for (i = 1; i < RACE_ATTACKS; ++i) + rc->attack[i].type = AT_NONE; rc->index = num_races++; ++cache_breaker; rc->next = races; diff --git a/src/kernel/race.h b/src/kernel/race.h index cccc88167..b9c541aa1 100644 --- a/src/kernel/race.h +++ b/src/kernel/race.h @@ -40,6 +40,8 @@ extern "C" { #define RACESPOILCHANCE 5 /* Chance auf rassentypische Beute */ +#define RACE_ATTACKS 10 /* maximum number of attacks */ + struct param; struct spell; @@ -121,9 +123,9 @@ extern "C" { struct param *parameters; char *_name; float magres; - float maxaura; /* Faktor auf Maximale Aura */ - float regaura; /* Faktor auf Regeneration */ - float recruit_multi; /* Faktor fr Bauernverbrauch */ + double maxaura; /* Faktor auf Maximale Aura */ + double regaura; /* Faktor auf Regeneration */ + double recruit_multi; /* Faktor fr Bauernverbrauch */ int index; int recruitcost; int maintenance; @@ -144,8 +146,7 @@ extern "C" { int flags; int battle_flags; int ec_flags; - race_t oldfamiliars[MAXMAGIETYP]; - struct att attack[10]; + struct att attack[RACE_ATTACKS]; signed char bonus[MAXSKILLS]; const char *(*generate_name) (const struct unit *); @@ -215,7 +216,7 @@ extern "C" { #define RCF_IRONGOLEM (1<<28) /* race gets irongolem properties */ /* Economic flags */ -#define GIVEITEM (1<<1) /* gibt Gegenstnde weg */ +#define ECF_KEEP_ITEM (1<<1) /* gibt Gegenstnde weg */ #define GIVEPERSON (1<<2) /* bergibt Personen */ #define GIVEUNIT (1<<3) /* Einheiten an andere Partei bergeben */ #define GETITEM (1<<4) /* nimmt Gegenstnde an */ diff --git a/src/kernel/region.c b/src/kernel/region.c index a4ed45b46..ddaab10d1 100644 --- a/src/kernel/region.c +++ b/src/kernel/region.c @@ -42,7 +42,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. /* util includes */ #include #include -#include +#include #include #include #include @@ -121,7 +121,7 @@ const char *write_regionname(const region * r, const faction * f, char *buffer, plane *pl = rplane(r); int nx = r->x, ny = r->y; pnormalize(&nx, &ny, pl); - adjust_coordinates(f, &nx, &ny, pl, r); + adjust_coordinates(f, &nx, &ny, pl); slprintf(buf, size, "%s (%d,%d)", rname(r, lang), nx, ny); } return buffer; @@ -537,11 +537,12 @@ attrib_type at_travelunit = { NO_READ }; -void rsetroad(region * r, direction_t d, short val) +void rsetroad(region * r, direction_t d, int val) { connection *b; region *r2 = rconnect(r, d); + assert(val>=SHRT_MIN && val<=SHRT_MAX); if (!r2) { return; } @@ -554,14 +555,14 @@ void rsetroad(region * r, direction_t d, short val) b = new_border(&bt_road, r, r2); } if (r == b->from) { - b->data.sa[0] = val; + b->data.sa[0] = (short)val; } else { - b->data.sa[1] = val; + b->data.sa[1] = (short)val; } } -short rroad(const region * r, direction_t d) +int rroad(const region * r, direction_t d) { connection *b; region *r2 = rconnect(r, d); @@ -956,8 +957,10 @@ void setluxuries(region * r, const luxury_type * sale) assert(r->land); - if (r->land->demands) + if (r->land->demands) { freelist(r->land->demands); + r->land->demands = 0; + } for (ltype = luxurytypes; ltype; ltype = ltype->next) { struct demand *dmd = malloc(sizeof(struct demand)); diff --git a/src/kernel/region.h b/src/kernel/region.h index b9558427a..5c2c3a17c 100644 --- a/src/kernel/region.h +++ b/src/kernel/region.h @@ -187,8 +187,8 @@ extern "C" { void setluxuries(struct region *r, const struct luxury_type *sale); int get_maxluxuries(void); - short rroad(const struct region *r, direction_t d); - void rsetroad(struct region *r, direction_t d, short value); + int rroad(const struct region *r, direction_t d); + void rsetroad(struct region *r, direction_t d, int value); bool is_coastregion(struct region *r); diff --git a/src/kernel/save.c b/src/kernel/save.c index db9999148..1d610d013 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 1998-2015, Enno Rehling Katja Zedel @@ -139,7 +139,8 @@ static unit *unitorders(FILE * F, int enc, struct faction *f) ordp = &u->old_orders; while (*ordp) { order *ord = *ordp; - if (!is_repeated(ord)) { + keyword_t kwd = getkeyword(ord); + if (!is_repeated(kwd)) { *ordp = ord->next; ord->next = NULL; free_order(ord); @@ -200,7 +201,7 @@ static unit *unitorders(FILE * F, int enc, struct faction *f) } } } - /* Nun wird der Befehl erzeut und eingehngt */ + /* Nun wird der Befehl erzeut und eingehängt */ *ordp = parse_order(s, u->faction->locale); if (*ordp) { ordp = &(*ordp)->next; @@ -233,8 +234,8 @@ static faction *factionorders(void) f->no, pass)); return 0; } - /* Die Partei hat sich zumindest gemeldet, so da sie noch - * nicht als unttig gilt */ + /* Die Partei hat sich zumindest gemeldet, so dass sie noch + * nicht als untätig gilt */ /* TODO: +1 ist ein Workaround, weil cturn erst in process_orders * incrementiert wird. */ @@ -308,9 +309,9 @@ int readorders(const char *filename) /* Falls in unitorders() abgebrochen wird, steht dort entweder eine neue * Partei, eine neue Einheit oder das File-Ende. Das switch() wird erneut * durchlaufen, und die entsprechende Funktion aufgerufen. Man darf buf - * auf alle Flle nicht berschreiben! Bei allen anderen Eintrgen hier - * mu buf erneut gefllt werden, da die betreffende Information in nur - * einer Zeile steht, und nun die nchste gelesen werden mu. */ + * auf alle Fälle nicht überschreiben! Bei allen anderen Einträgen hier + * muss buf erneut gefüllt werden, da die betreffende Information in nur + * einer Zeile steht, und nun die nächste gelesen werden muss. */ case P_NEXT: f = NULL; @@ -331,7 +332,7 @@ int readorders(const char *filename) /* ------------------------------------------------------------- */ /* #define INNER_WORLD */ -/* frs debuggen nur den inneren Teil der Welt laden */ +/* fürs debuggen nur den inneren Teil der Welt laden */ /* -9;-27;-1;-19;Sumpfloch */ int inner_world(region * r) { @@ -618,13 +619,13 @@ unit *read_unit(struct gamedata *data) } READ_STR(data->store, obuf, sizeof(obuf)); - u->name = _strdup(obuf); + u->_name = obuf[0] ? _strdup(obuf) : 0; if (lomem) { READ_STR(data->store, NULL, 0); } else { READ_STR(data->store, obuf, sizeof(obuf)); - u->display = _strdup(obuf); + u->display = obuf[0] ? _strdup(obuf) : 0; } READ_INT(data->store, &number); set_number(u, number); @@ -754,8 +755,8 @@ void write_unit(struct gamedata *data, const unit * u) write_unit_reference(u, data->store); write_faction_reference(u->faction, data->store); - WRITE_STR(data->store, (const char *)u->name); - WRITE_STR(data->store, u->display ? (const char *)u->display : ""); + WRITE_STR(data->store, u->_name); + WRITE_STR(data->store, u->display ? u->display : ""); WRITE_INT(data->store, u->number); WRITE_INT(data->store, u->age); WRITE_TOK(data->store, u_race(u)->_name); @@ -777,7 +778,8 @@ void write_unit(struct gamedata *data, const unit * u) } } for (ord = u->orders; ord; ord = ord->next) { - if (u->old_orders && is_repeated(ord)) + keyword_t kwd = getkeyword(ord); + if (u->old_orders && is_repeated(kwd)) continue; /* has new defaults */ if (is_persistent(ord)) { if (++p < MAXPERSISTENT) { @@ -978,6 +980,9 @@ static region *readregion(struct gamedata *data, int x, int y) void writeregion(struct gamedata *data, const region * r) { + assert(r); + assert(data); + WRITE_INT(data->store, r->uid); WRITE_STR(data->store, region_getinfo(r)); WRITE_TOK(data->store, r->terrain->_name); @@ -988,6 +993,8 @@ void writeregion(struct gamedata *data, const region * r) const item_type *rht; struct demand *demand; rawmaterial *res = r->resources; + + assert(r->land); WRITE_STR(data->store, (const char *)r->land->name); assert(rtrees(r, 0) >= 0); assert(rtrees(r, 1) >= 0); @@ -1018,11 +1025,9 @@ void writeregion(struct gamedata *data, const region * r) WRITE_INT(data->store, rherbs(r)); WRITE_INT(data->store, rpeasants(r)); WRITE_INT(data->store, rmoney(r)); - if (r->land) { - for (demand = r->land->demands; demand; demand = demand->next) { - WRITE_TOK(data->store, resourcename(demand->type->itype->rtype, 0)); - WRITE_INT(data->store, demand->value); - } + for (demand = r->land->demands; demand; demand = demand->next) { + WRITE_TOK(data->store, resourcename(demand->type->itype->rtype, 0)); + WRITE_INT(data->store, demand->value); } WRITE_TOK(data->store, "end"); write_items(data->store, r->land->items); @@ -1119,7 +1124,7 @@ void read_spellbook(spellbook **bookp, struct storage *store, int(*get_level)(co *bookp = create_spellbook(0); sb = *bookp; } - if (global.data_version >= SPELLBOOK_VERSION || !spellbook_get(sb, sp)) { + if (level>0 && (global.data_version >= SPELLBOOK_VERSION || !spellbook_get(sb, sp))) { spellbook_add(sb, sp, level); } } @@ -1250,7 +1255,7 @@ faction *readfaction(struct gamedata * data) READ_INT(data->store, &id); READ_INT(data->store, &ux); READ_INT(data->store, &uy); - set_ursprung(f, id, ux, uy); + faction_setorigin(f, id, ux, uy); } f->newbies = 0; @@ -1262,7 +1267,10 @@ faction *readfaction(struct gamedata * data) /* Kein Report eingestellt, Fehler */ f->options |= n; } - + if (data->version < JSON_REPORT_VERSION) { + /* mistakes were made in the past*/ + f->options &= ~want(O_JSON); + } sfp = &f->allies; for (;;) { int aid = 0; @@ -1345,7 +1353,7 @@ void writefaction(struct gamedata *data, const faction * f) write_spellbook(f->spellbook, data->store); } -int readgame(const char *filename, int backup) +int readgame(const char *filename, bool backup) { int n, p, nread; faction *f, **fp; @@ -1382,7 +1390,7 @@ int readgame(const char *filename, int backup) assert(stream_version == STREAM_VERSION || !"unsupported data format"); } assert(gdata.version >= MIN_VERSION || !"unsupported data format"); - assert(gdata.version <= RELEASE_VERSION || !"unsupported data format"); + assert(gdata.version <= MAX_VERSION || !"unsupported data format"); gdata.encoding = enc_gamedata; fstream_init(&strm, F); @@ -1597,11 +1605,10 @@ int readgame(const char *filename, int backup) while (--p >= 0) { unit *u = read_unit(&gdata); - sc_mage *mage; - if (gdata.version < AUTO_RACENAME_VERSION) { - if (u->name && fval(u->faction, FFL_NPC)) { - if (unit_name_equals_race(u)) { + if (gdata.version < JSON_REPORT_VERSION) { + if (u->_name && fval(u->faction, FFL_NPC)) { + if (!u->_name[0] || unit_name_equals_race(u)) { unit_setname(u, NULL); } } @@ -1612,21 +1619,6 @@ int readgame(const char *filename, int backup) up = &u->next; update_interval(u->faction, u->region); - mage = get_mage(u); - if (mage) { - faction *f = u->faction; - int skl = effskill(u, SK_MAGIC); - if (!fval(f, FFL_NPC) && f->magiegebiet == M_GRAY) { - log_error("faction %s had magic=gray, fixing (%s)\n", factionname(f), magic_school[mage->magietyp]); - f->magiegebiet = mage->magietyp; - } - if (f->max_spelllevel < skl) { - f->max_spelllevel = skl; - } - if (mage->spellcount < 0) { - mage->spellcount = 0; - } - } } } log_printf(stdout, "\n"); @@ -1650,6 +1642,7 @@ int readgame(const char *filename, int backup) for (f = factions; f; f = f->next) { if (f->flags & FFL_NPC) { f->alive = 1; + f->magiegebiet = M_GRAY; if (f->no == 0) { int no = 666; while (findfaction(no)) @@ -1660,8 +1653,23 @@ int readgame(const char *filename, int backup) } else { for (u = f->units; u; u = u->nextF) { + sc_mage *mage = get_mage(u); + if (mage) { + faction *f = u->faction; + int skl = effskill(u, SK_MAGIC); + if (f->magiegebiet == M_GRAY) { + log_error("faction %s had magic=gray, fixing (%s)\n", factionname(f), magic_school[mage->magietyp]); + f->magiegebiet = mage->magietyp; + } + if (f->max_spelllevel < skl) { + f->max_spelllevel = skl; + } + if (mage->spellcount < 0) { + mage->spellcount = 0; + } + } if (u->number > 0) { - f->alive = 1; + f->alive = true; break; } } @@ -1721,6 +1729,7 @@ int writegame(const char *filename) gdata.store = &store; gdata.encoding = enc_gamedata; gdata.version = RELEASE_VERSION; + global.data_version = RELEASE_VERSION; n = STREAM_VERSION; fwrite(&gdata.version, sizeof(int), 1, F); fwrite(&n, sizeof(int), 1, F); diff --git a/src/kernel/save.h b/src/kernel/save.h index ee731fab8..11b53d620 100644 --- a/src/kernel/save.h +++ b/src/kernel/save.h @@ -44,7 +44,7 @@ extern "C" { int readorders(const char *filename); int creategame(void); - int readgame(const char *filename, int backup); + int readgame(const char *filename, bool backup); int writegame(const char *filename); /* Versionsnderungen: */ diff --git a/src/kernel/save.test.c b/src/kernel/save.test.c index cdbdbd3bf..26f48a07f 100644 --- a/src/kernel/save.test.c +++ b/src/kernel/save.test.c @@ -15,7 +15,7 @@ static void test_readwrite_data(CuTest * tc) test_cleanup(); sprintf(path, "%s/%s", datapath(), filename); CuAssertIntEquals(tc, 0, writegame(filename)); - CuAssertIntEquals(tc, 0, readgame(filename, 0)); + CuAssertIntEquals(tc, 0, readgame(filename, false)); CuAssertIntEquals(tc, RELEASE_VERSION, global.data_version); CuAssertIntEquals(tc, 0, remove(path)); test_cleanup(); diff --git a/src/kernel/ship.c b/src/kernel/ship.c index 1ae81b436..a01326bdd 100644 --- a/src/kernel/ship.c +++ b/src/kernel/ship.c @@ -435,13 +435,25 @@ void write_ship_reference(const struct ship *sh, struct storage *store) void ship_setname(ship * self, const char *name) { free(self->name); - if (name) - self->name = _strdup(name); - else - self->name = NULL; + self->name = name ? _strdup(name) : 0; } const char *ship_getname(const ship * self) { return self->name; } + +unit *get_captain(const ship * sh) +{ + const region *r = sh->region; + unit *u; + + for (u = r->units; u; u = u->next) { + if (u->ship == sh && u->number + && eff_skill(u, SK_SAILING, r) >= sh->type->cptskill) + return u; + } + + return NULL; +} + diff --git a/src/kernel/ship.h b/src/kernel/ship.h index 809e678a4..f123242df 100644 --- a/src/kernel/ship.h +++ b/src/kernel/ship.h @@ -121,9 +121,10 @@ extern "C" { extern void free_ship(struct ship *s); extern void free_ships(void); - extern const char *ship_getname(const struct ship *self); - extern void ship_setname(struct ship *self, const char *name); + const char *ship_getname(const struct ship *self); + void ship_setname(struct ship *self, const char *name); int shipspeed(const struct ship *sh, const struct unit *u); + struct unit *get_captain(const struct ship *sh); #ifdef __cplusplus } diff --git a/src/kernel/skills.h b/src/kernel/skills.h index a7f4e99f9..192030dcf 100644 --- a/src/kernel/skills.h +++ b/src/kernel/skills.h @@ -32,9 +32,9 @@ extern "C" { unsigned int old:8; #else int id; - unsigned int level; - unsigned int weeks; - unsigned int old; + int level; + int weeks; + int old; #endif } skill; diff --git a/src/kernel/spell.c b/src/kernel/spell.c index 2e95de30c..b9a8b5895 100644 --- a/src/kernel/spell.c +++ b/src/kernel/spell.c @@ -22,7 +22,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. /* util includes */ #include -#include +#include #include #include #include @@ -78,6 +78,7 @@ static const char *sp_aliases[][2] = { { "illaunfamiliar", "summon_familiar" }, { "draigfamiliar", "summon_familiar" }, { "commonfamiliar", "summon_familiar" }, + { "cerrdorfumbleshield", "cerddorfumbleshield" }, { NULL, NULL }, }; diff --git a/src/kernel/spellid.h b/src/kernel/spellid.h index ce324874b..387c592db 100644 --- a/src/kernel/spellid.h +++ b/src/kernel/spellid.h @@ -136,7 +136,7 @@ enum { SPL_GWYRRD_ARMORSHIELD, SPL_DRAIG_FUMBLESHIELD, SPL_GWYRRD_FUMBLESHIELD, - SPL_CERRDOR_FUMBLESHIELD, + SPL_CERDDOR_FUMBLESHIELD, SPL_TYBIED_FUMBLESHIELD, SPL_SHADOWKNIGHTS = 147, SPL_ITEMCLOAK = 150, diff --git a/src/kernel/terrain.c b/src/kernel/terrain.c index f89144a6f..36efb3591 100644 --- a/src/kernel/terrain.c +++ b/src/kernel/terrain.c @@ -35,7 +35,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include -#define MAXTERRAINS 20 +#define MAXTERRAINS 14 const char *terraindata[MAXTERRAINS] = { "ocean", @@ -46,19 +46,12 @@ const char *terraindata[MAXTERRAINS] = { "mountain", "glacier", "firewall", - NULL, /* dungeon module */ - NULL, /* former grassland */ "fog", "thickfog", "volcano", "activevolcano", "iceberg_sleep", - "iceberg", - - NULL, /* museum module */ - NULL, /* museum module */ - NULL, /* former magicstorm */ - NULL /* museum module */ + "iceberg" }; static terrain_type *registered_terrains; @@ -140,7 +133,7 @@ terrain_t oldterrain(const struct terrain_type * terrain) if (newterrains[t] == terrain) return t; } - log_warning("%s is not a classic terrain.\n", terrain->_name); + log_debug("%s is not a classic terrain.\n", terrain->_name); return NOTERRAIN; } diff --git a/src/kernel/terrainid.h b/src/kernel/terrainid.h index 0685a60e9..7d353d042 100644 --- a/src/kernel/terrainid.h +++ b/src/kernel/terrainid.h @@ -16,25 +16,19 @@ extern "C" { enum { T_OCEAN = 0, - T_PLAIN = 1, - T_SWAMP = 2, - T_DESERT = 3, /* kann aus T_PLAIN entstehen */ - T_HIGHLAND = 4, - T_MOUNTAIN = 5, - T_GLACIER = 6, /* kann aus T_MOUNTAIN entstehen */ - T_FIREWALL = 7, /* Unpassierbar */ - /* T_HELL = 8, Hlle */ - /* T_GRASSLAND = 9, */ - T_ASTRAL = 10, - T_ASTRALB = 11, - T_VOLCANO = 12, - T_VOLCANO_SMOKING = 13, - T_ICEBERG_SLEEP = 14, - T_ICEBERG = 15, - /* T_HALL1 = 16, */ - /* T_CORRIDOR1 = 17, */ - /* T_MAGICSTORM = 18, */ - /* T_WALL1 = 19, */ + T_PLAIN, + T_SWAMP, + T_DESERT, + T_HIGHLAND, + T_MOUNTAIN, + T_GLACIER, + T_FIREWALL, + T_ASTRAL, + T_ASTRALB, + T_VOLCANO, + T_VOLCANO_SMOKING, + T_ICEBERG_SLEEP, + T_ICEBERG, NOTERRAIN = (terrain_t) - 1 }; diff --git a/src/kernel/types.h b/src/kernel/types.h index 27a5925ca..632dad425 100644 --- a/src/kernel/types.h +++ b/src/kernel/types.h @@ -167,7 +167,7 @@ enum { O_REPORT, /* 1 */ O_COMPUTER, /* 2 */ O_ZUGVORLAGE, /* 4 */ - O_UNUSED_3, + O_JSON, /* 8 */ O_STATISTICS, /* 16 */ O_DEBUG, /* 32 */ O_COMPRESS, /* 64 */ diff --git a/src/kernel/unit.c b/src/kernel/unit.c index 2b987c572..85e558fd2 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -48,7 +48,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include #include -#include +#include #include #include #include @@ -257,9 +257,9 @@ static buddy *get_friends(const unit * u, int *numfriends) *fr = nf; } else if (nf->faction == u2->faction - && (u_race(u2)->ec_flags & GIVEITEM)) { + && !(u_race(u2)->ec_flags & ECF_KEEP_ITEM)) { /* we don't like to gift it to units that won't give it back */ - if ((u_race(nf->unit)->ec_flags & GIVEITEM) == 0) { + if ((u_race(nf->unit)->ec_flags & ECF_KEEP_ITEM)) { nf->unit = u2; } } @@ -300,7 +300,7 @@ int gift_items(unit * u, int flags) if (u->items == NULL || fval(u_race(u), RCF_ILLUSIONARY)) return 0; - if ((u_race(u)->ec_flags & GIVEITEM) == 0) + if ((u_race(u)->ec_flags & ECF_KEEP_ITEM)) return 0; /* at first, I should try giving my crap to my own units in this region */ @@ -311,7 +311,7 @@ int gift_items(unit * u, int flags) /* some units won't take stuff: */ if (u_race(u2)->ec_flags & GETITEM) { /* we don't like to gift it to units that won't give it back */ - if (u_race(u2)->ec_flags & GIVEITEM) { + if (!(u_race(u2)->ec_flags & ECF_KEEP_ITEM)) { i_merge(&u2->items, &u->items); u->items = NULL; break; @@ -1277,7 +1277,7 @@ static int item_modification(const unit * u, skill_t sk, int val) static int att_modification(const unit * u, skill_t sk) { double result = 0; - static bool init = false; + static bool init = false; // TODO: static variables are bad global state static const curse_type *skillmod_ct, *gbdream_ct, *worse_ct; curse *c; @@ -1306,25 +1306,19 @@ static int att_modification(const unit * u, skill_t sk) /* TODO hier kann nicht mit get/iscursed gearbeitet werden, da nur der * jeweils erste vom Typ C_GBDREAM zurueckgegen wird, wir aber alle * durchsuchen und aufaddieren muessen */ - if (u->region) { - double bonus = 0, malus = 0; + if (gbdream_ct && u->region) { + int bonus = 0, malus = 0; attrib *a = a_find(u->region->attribs, &at_curse); while (a && a->type == &at_curse) { curse *c = (curse *)a->data.v; + if (curse_active(c) && c->type == gbdream_ct) { - double mod = curse_geteffect(c); - unit *mage = c->magician; - /* wir suchen jeweils den groesten Bonus und den groesten Malus */ - if (mod > bonus) { - if (mage == NULL || mage->number == 0 - || alliedunit(mage, u->faction, HELP_GUARD)) { - bonus = mod; - } - } - else if (mod < malus) { - if (mage == NULL || !alliedunit(mage, u->faction, HELP_GUARD)) { - malus = mod; - } + int effect = curse_geteffect_int(c); + bool allied = alliedunit(c->magician, u->faction, HELP_GUARD); + if (allied) { + if (effect > bonus) bonus = effect; + } else { + if (effect < malus) malus = effect; } } a = a->next; @@ -1430,7 +1424,7 @@ int invisible(const unit * target, const unit * viewer) */ void free_unit(unit * u) { - free(u->name); + free(u->_name); free(u->display); free_order(u->thisorder); free_orders(&u->orders); @@ -1461,6 +1455,28 @@ static void createunitid(unit * u, int id) uhash(u); } +void default_name(const unit *u, char name[], int len) { + const char * result; + const struct locale * lang = u->faction ? u->faction->locale : default_locale; + if (lang) { + static const char * prefix[MAXLOCALES]; + int i = locale_index(lang); + /*if (!prefix[i]) {*/ + prefix[i] = LOC(lang, "unitdefault"); + if (!prefix[i]) { + prefix[i] = parameters[P_UNIT]; + } + /*}*/ + result = prefix[i]; + } + else { + result = parameters[P_UNIT]; + } + strlcpy(name, result, len); + strlcat(name, " ", len); + strlcat(name, itoa36(u->no), len); +} + void name_unit(unit * u) { if (u_race(u)->generate_name) { @@ -1474,25 +1490,7 @@ void name_unit(unit * u) } else { char name[32]; - const char * result; - const struct locale * lang = u->faction ? u->faction->locale : default_locale; - if (lang) { - static const char * prefix[MAXLOCALES]; - int i = locale_index(lang); - if (!prefix[i]) { - prefix[i] = LOC(lang, "unitdefault"); - if (!prefix[i]) { - prefix[i] = parameters[P_UNIT]; - } - } - result = prefix[i]; - } - else { - result = parameters[P_UNIT]; - } - strlcpy(name, result, sizeof(name)); - strlcat(name, " ", sizeof(name)); - strlcat(name, itoa36(u->no), sizeof(name)); + default_name(u, name, sizeof(name)); unit_setname(u, name); } } @@ -1542,7 +1540,7 @@ unit *create_unit(region * r, faction * f, int number, const struct race *urace, name_unit(u); } else { - u->name = _strdup(dname); + u->_name = _strdup(dname); } if (creator) { @@ -1631,18 +1629,24 @@ int countheroes(const struct faction *f) return n; } +/** Returns the raw unit name, like "Frodo", or "Seeschlange" */ const char *unit_getname(const unit * u) { - return (const char *)u->name; + if (!u->_name) { + const struct locale * lang = u->faction ? u->faction->locale : default_locale; + const char *rcname = rc_name_s(u->_race, u->number == 1 ? NAME_SINGULAR : NAME_PLURAL); + return LOC(lang, rcname); + } + return u->_name; } void unit_setname(unit * u, const char *name) { - free(u->name); - if (name) - u->name = _strdup(name); + free(u->_name); + if (name && name[0]) + u->_name = _strdup(name); else - u->name = NULL; + u->_name = NULL; } const char *unit_getinfo(const unit * u) @@ -1878,20 +1882,16 @@ typedef char name[OBJECTIDSIZE + 1]; static name idbuf[8]; static int nextbuf = 0; +/** Puts human-readable unit name, with number, like "Frodo (hobb)" into buffer */ char *write_unitname(const unit * u, char *buffer, size_t size) { - if (u->name) { - slprintf(buffer, size, "%s (%s)", u->name, itoa36(u->no)); - } - else { - const struct locale * lang = u->faction ? u->faction->locale : default_locale; - const char * name = rc_name_s(u->_race, u->number == 1 ? NAME_SINGULAR : NAME_PLURAL); - slprintf(buffer, size, "%s (%s)", LOC(lang, name), itoa36(u->no)); - } + const char * name = unit_getname(u); + slprintf(buffer, size, "%s (%s)", name, itoa36(u->no)); buffer[size - 1] = 0; return buffer; } +/** Returns human-readable unit name, with number, like "Frodo (hobb)" */ const char *unitname(const unit * u) { char *ubuf = idbuf[(++nextbuf) % 8]; @@ -1899,14 +1899,14 @@ const char *unitname(const unit * u) } bool unit_name_equals_race(const unit *u) { - if (u->name) { + if (u->_name) { char sing[32], plur[32]; const struct locale *lang = u->faction->locale; rc_name(u->_race, NAME_SINGULAR, sing, sizeof(sing)); rc_name(u->_race, NAME_PLURAL, plur, sizeof(plur)); - if (strcmp(u->name, sing) == 0 || strcmp(u->name, plur) == 0 || - strcmp(u->name, LOC(lang, sing)) == 0 || - strcmp(u->name, LOC(lang, plur)) == 0) { + if (strcmp(u->_name, sing) == 0 || strcmp(u->_name, plur) == 0 || + strcmp(u->_name, LOC(lang, sing)) == 0 || + strcmp(u->_name, LOC(lang, plur)) == 0) { return true; } } @@ -1915,4 +1915,4 @@ bool unit_name_equals_race(const unit *u) { bool unit_can_study(const unit *u) { return !((u_race(u)->flags & RCF_NOLEARN) || fval(u, UFL_WERE)); -} \ No newline at end of file +} diff --git a/src/kernel/unit.h b/src/kernel/unit.h index 5fd40c57e..c84ccbdfe 100644 --- a/src/kernel/unit.h +++ b/src/kernel/unit.h @@ -82,14 +82,14 @@ extern "C" { struct unit *nextF; /* nchste Einheit der Partei */ struct unit *prevF; /* vorherige Einheit der Partei */ struct region *region; - int no; + int no; /* id */ int hp; - char *name; + char *_name; char *display; struct faction *faction; struct building *building; struct ship *ship; - unsigned short number; + unsigned short number; /* persons */ short age; /* skill data */ @@ -110,7 +110,7 @@ extern "C" { int flags; struct attrib *attribs; status_t status; - int n; /* enno: attribut? */ + int n; /* helper temporariy variable, used in econmy, enno: attribut? */ int wants; /* enno: attribut? */ } unit; @@ -248,6 +248,7 @@ extern "C" { struct unit *findunitr(const struct region *r, int n); + void default_name(const unit *u, char name[], int len); const char *unitname(const struct unit *u); char *write_unitname(const struct unit *u, char *buffer, size_t size); bool unit_name_equals_race(const struct unit *u); diff --git a/src/kernel/unit.test.c b/src/kernel/unit.test.c index 76d708721..7f281fc36 100644 --- a/src/kernel/unit.test.c +++ b/src/kernel/unit.test.c @@ -1,13 +1,20 @@ #include #include +#include +#include +#include +#include +#include +#include +#include #include #include -#include "alchemy.h" -#include "faction.h" +#include +#include +#include +#include +#include #include "unit.h" -#include "item.h" -#include "race.h" -#include "region.h" #include #include @@ -155,10 +162,12 @@ static void test_unit_name_from_race(CuTest *tc) { _snprintf(name, sizeof(name), "Mensch (%s)", itoa36(u->no)); CuAssertStrEquals(tc, name, unitname(u)); + CuAssertStrEquals(tc, "Mensch", unit_getname(u)); u->number = 2; _snprintf(name, sizeof(name), "Menschen (%s)", itoa36(u->no)); CuAssertStrEquals(tc, name, unitname(u)); + CuAssertStrEquals(tc, "Menschen", unit_getname(u)); test_cleanup(); } @@ -195,6 +204,42 @@ static void test_update_monster_name(CuTest *tc) { test_cleanup(); } +static void test_names(CuTest *tc) { + unit *u; + + test_cleanup(); + test_create_world(); + u = test_create_unit(test_create_faction(test_create_race("human")), findregion(0, 0)); + + unit_setname(u, "Hodor"); + unit_setid(u, 5); + CuAssertStrEquals(tc, "Hodor", unit_getname(u)); + CuAssertStrEquals(tc, "Hodor (5)", unitname(u)); + test_cleanup(); +} + +static void test_default_name(CuTest *tc) { + unit *u; + struct locale* lang; + char buf[32], compare[32]; + + test_cleanup(); + test_create_world(); + lang = get_or_create_locale("de"); + /* FIXME this has no real effect: default_name uses a static buffer that is initialized in some other test. This sucks. */ + locale_setstring(lang, "unitdefault", "Einheit"); + + u = test_create_unit(test_create_faction(test_create_race("human")), findregion(0, 0)); + + default_name(u, buf, sizeof(buf)); + + sprintf(compare, "Einheit %s", itoa36(u->no)); + CuAssertStrEquals(tc, compare, buf); + + test_cleanup(); +} + + CuSuite *get_unit_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -207,5 +252,7 @@ CuSuite *get_unit_suite(void) SUITE_ADD_TEST(suite, test_remove_units_without_faction); SUITE_ADD_TEST(suite, test_remove_units_with_dead_faction); SUITE_ADD_TEST(suite, test_remove_empty_units_in_region); + SUITE_ADD_TEST(suite, test_names); + SUITE_ADD_TEST(suite, test_default_name); return suite; } diff --git a/src/kernel/version.h b/src/kernel/version.h index 516893437..430628157 100644 --- a/src/kernel/version.h +++ b/src/kernel/version.h @@ -28,8 +28,11 @@ #define SAVEGAMEID_VERSION 343 /* instead of XMLNAME, save the game.id parameter from the config */ #define BUILDNO_VERSION 344 /* storing the build number in the save */ #define AUTO_RACENAME_VERSION 345 /* NPC units with name==NULL will automatically get their race for a name */ +#define JSON_REPORT_VERSION 346 /* bit 3 in f->options flags the json report */ +#define EXPLICIT_CURSE_ISNEW_VERSION 347 /* CURSE_ISNEW is not reset in read/write, but in age() */ +#define RELEASE_VERSION EXPLICIT_CURSE_ISNEW_VERSION /* current datafile */ #define MIN_VERSION INTPAK_VERSION /* minimal datafile we support */ -#define RELEASE_VERSION AUTO_RACENAME_VERSION /* current datafile */ +#define MAX_VERSION RELEASE_VERSION /* change this if we can need to read the future datafile, and we can do so */ #define STREAM_VERSION 2 /* internal encoding of binary files */ diff --git a/src/kernel/xmlreader.c b/src/kernel/xmlreader.c index 14f9f8f56..fca49e8ff 100644 --- a/src/kernel/xmlreader.c +++ b/src/kernel/xmlreader.c @@ -31,6 +31,10 @@ without prior permission by the authors of Eressea. #include "vortex.h" +#if SCORE_MODULE +#include +#endif + /* util includes */ #include #include @@ -766,9 +770,6 @@ static item_type *xml_readitem(xmlXPathContextPtr xpath, resource_type * rtype) itype->weight = xml_ivalue(node, "weight", 0); itype->capacity = xml_ivalue(node, "capacity", 0); itype->flags |= flags; -#if SCORE_MODULE - itype->score = xml_ivalue(node, "score", 0); -#endif /* reading item/construction */ xpath->node = node; @@ -855,6 +856,10 @@ static item_type *xml_readitem(xmlXPathContextPtr xpath, resource_type * rtype) } xmlFree(propValue); } +#if SCORE_MODULE + itype->score = xml_ivalue(node, "score", 0); + if (!itype->score) itype->score = default_score(itype); +#endif xmlXPathFreeObject(result); return itype; @@ -1608,9 +1613,9 @@ static int parse_races(xmlDocPtr doc) xmlNodePtr node = nodes->nodeTab[i]; xmlNodePtr child; xmlChar *propValue; - race *rc; + race *rc, *frc = 0; xmlXPathObjectPtr result; - int k, study_speed_base; + int k, study_speed_base, attacks; struct att *attack; propValue = xmlGetProp(node, BAD_CAST "name"); @@ -1693,8 +1698,8 @@ static int parse_races(xmlDocPtr doc) if (xml_bvalue(node, "irongolem", false)) rc->flags |= RCF_IRONGOLEM; - if (xml_bvalue(node, "giveitem", false)) - rc->ec_flags |= GIVEITEM; + if (xml_bvalue(node, "keepitem", false)) + rc->ec_flags |= ECF_KEEP_ITEM; if (xml_bvalue(node, "giveperson", false)) rc->ec_flags |= GIVEPERSON; if (xml_bvalue(node, "giveunit", false)) @@ -1721,7 +1726,7 @@ static int parse_races(xmlDocPtr doc) if (xml_bvalue(node, "resistpierce", false)) rc->battle_flags |= BF_RES_PIERCE; if (xml_bvalue(node, "canattack", true)) - rc->battle_flags |= BF_CANATTACK; + rc->battle_flags |= BF_CANATTACK; // TODO: invert this flag, so rc_get_or_create gets simpler for (child = node->children; child; child = child->next) { if (strcmp((const char *)child->name, "ai") == 0) { @@ -1805,21 +1810,27 @@ static int parse_races(xmlDocPtr doc) /* reading eressea/races/race/familiar */ xpath->node = node; result = xmlXPathEvalExpression(BAD_CAST "familiar", xpath); - for (k = 0; k != result->nodesetval->nodeNr; ++k) { - xmlNodePtr node = result->nodesetval->nodeTab[k]; - race *frc; + if (result->nodesetval->nodeNr > MAXMAGIETYP) { + log_error("race %s has %d potential familiars", rc->_name, result->nodesetval->nodeNr); + } + for (k = 0; k != MAXMAGIETYP; ++k) { + if (k < result->nodesetval->nodeNr) { + xmlNodePtr node = result->nodesetval->nodeTab[k]; - propValue = xmlGetProp(node, BAD_CAST "race"); - assert(propValue != NULL); - frc = rc_get_or_create((const char *)propValue); - if (xml_bvalue(node, "default", false)) { - rc->familiars[k] = rc->familiars[0]; - rc->familiars[0] = frc; - } - else { + propValue = xmlGetProp(node, BAD_CAST "race"); + assert(propValue != NULL); + frc = rc_get_or_create((const char *)propValue); + if (xml_bvalue(node, "default", false)) { + rc->familiars[k] = rc->familiars[0]; + rc->familiars[0] = frc; + } + else { + rc->familiars[k] = frc; + } + xmlFree(propValue); + } else { rc->familiars[k] = frc; } - xmlFree(propValue); } xmlXPathFreeObject(result); @@ -1838,10 +1849,16 @@ static int parse_races(xmlDocPtr doc) xpath->node = node; result = xmlXPathEvalExpression(BAD_CAST "attack", xpath); attack = rc->attack; + attacks = 0; for (k = 0; k != result->nodesetval->nodeNr; ++k) { xmlNodePtr node = result->nodesetval->nodeTab[k]; - while (attack->type != AT_NONE) + while (attack->type != AT_NONE) { ++attack; + if (attacks++ >= RACE_ATTACKS) { + log_error("too many attacks for race '%s'\n", rc->_name); + assert(!"aborting"); + } + } propValue = xmlGetProp(node, BAD_CAST "damage"); if (propValue != NULL) { diff --git a/src/keyword.c b/src/keyword.c index fde981bb9..683b1d2c2 100644 --- a/src/keyword.c +++ b/src/keyword.c @@ -12,7 +12,7 @@ const char * keyword(keyword_t kwd) { - static char result[KEYWORDSIZE]; // FIXME: static return value + static char result[32]; // FIXME: static return value if (!result[0]) { strcpy(result, "keyword::"); } @@ -58,7 +58,7 @@ keyword_t get_keyword(const char *s, const struct locale *lang) { if (str) { int i; - const void *match; + void *match; void **tokens = get_translations(lang, UT_KEYWORDS); critbit_tree *cb = (critbit_tree *)*tokens; if (cb && cb_find_prefix(cb, str, strlen(str), &match, 1, 0)) { diff --git a/src/laws.c b/src/laws.c index 7fc04876b..3f68294fb 100755 --- a/src/laws.c +++ b/src/laws.c @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 1998-2014, Enno Rehling Katja Zedel /* chance that a peasant dies of starvation: */ -#define PEASANT_STARVATION_CHANCE 0.9F +#define PEASANT_STARVATION_CHANCE 0.9 /* Pferdevermehrung */ #define HORSEGROWTH 4 /* Wanderungschance pro Pferd */ @@ -113,7 +113,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. /* - exported global symbols ----------------------------------- */ -static int RemoveNMRNewbie(void) +static bool RemoveNMRNewbie(void) { static int value = -1; static int gamecookie = -1; @@ -122,17 +122,7 @@ static int RemoveNMRNewbie(void) value = get_param_int(global.parameters, "nmr.removenewbie", 0); gamecookie = global.cookie; } - return value; -} - -static void checkorders(void) -{ - faction *f; - - log_info(" - Warne spaete Spieler..."); - for (f = factions; f; f = f->next) - if (!is_monsters(f) && turn - f->lastorders == NMRTimeout() - 1) - ADDMSG(&f->msgs, msg_message("turnreminder", "")); + return value!=0; } static void age_unit(region * r, unit * u) @@ -175,7 +165,7 @@ static void live(region * r) while (*up) { unit *u = *up; /* IUW: age_unit() kann u loeschen, u->next ist dann - * undefiniert, also muessen wir hier schon das nchste + * undefiniert, also muessen wir hier schon das nächste * Element bestimmen */ int effect = get_effect(u, oldpotiontype[P_FOOL]); @@ -193,7 +183,7 @@ static void live(region * r) reduce_skill(u, sb, weeks); ADDMSG(&u->faction->msgs, msg_message("dumbeffect", "unit weeks skill", u, weeks, (skill_t)sb->id)); - } /* sonst Glck gehabt: wer nix wei, kann nix vergessen... */ + } /* sonst Glück gehabt: wer nix weiss, kann nix vergessen... */ change_effect(u, oldpotiontype[P_FOOL], -effect); } age_unit(r, u); @@ -257,7 +247,7 @@ static void calculate_emigration(region * r) } -static float peasant_growth_factor(void) +static double peasant_growth_factor(void) { return get_param_flt(global.parameters, "rules.peasants.growth.factor", 0.0001F * PEASANTGROWTH); } @@ -265,7 +255,7 @@ static float peasant_growth_factor(void) #ifdef SLOWLUCK int peasant_luck_effect(int peasants, int luck, int maxp, double variance) { int n, births=0; - float factor = peasant_growth_factor(); + double factor = peasant_growth_factor(); for (n = peasants; n && luck; --n) { int chances = 0; @@ -287,7 +277,7 @@ int peasant_luck_effect(int peasants, int luck, int maxp, double variance) { return births; } #else -static float peasant_luck_factor(void) +static double peasant_luck_factor(void) { return get_param_flt(global.parameters, "rules.peasants.peasantluck.factor", PEASANTLUCK); } @@ -296,12 +286,10 @@ int peasant_luck_effect(int peasants, int luck, int maxp, double variance) { int births = 0; double mean; - if (luck == 0) return 0; - mean = _min(luck, peasants) * peasant_luck_factor() - * peasant_growth_factor() * ((peasants / (double)maxp < .9) ? 1 : - PEASANTFORCE); + mean = peasant_luck_factor() * peasant_growth_factor() * _min(luck, peasants); + mean *= ((peasants / (double)maxp < .9) ? 1 : PEASANTFORCE); births = RAND_ROUND(normalvariate(mean, variance * mean)); if (births <= 0) @@ -337,19 +325,19 @@ static void peasants(region * r) peasants += births + luck; } - /* Alle werden satt, oder halt soviele fr die es auch Geld gibt */ + /* Alle werden satt, oder halt soviele für die es auch Geld gibt */ satiated = _min(peasants, money / maintenance_cost(NULL)); rsetmoney(r, money - satiated * maintenance_cost(NULL)); /* Von denjenigen, die nicht satt geworden sind, verhungert der - * Groteil. dead kann nie grer als rpeasants(r) - satiated werden, - * so dass rpeasants(r) >= 0 bleiben mu. */ + * Großteil. dead kann nie größer als rpeasants(r) - satiated werden, + * so dass rpeasants(r) >= 0 bleiben muß. */ - /* Es verhungert maximal die unterernhrten Bevlkerung. */ + /* Es verhungert maximal die unterernährten Bevölkerung. */ n = _min(peasants - satiated, rpeasants(r)); - dead += (int)(0.5F + n * PEASANT_STARVATION_CHANCE); + dead += (int)(0.5 + n * PEASANT_STARVATION_CHANCE); if (dead > 0) { message *msg = add_message(&r->msgs, msg_message("phunger", "dead", dead)); @@ -411,10 +399,10 @@ static void migrate(region * r) rsethorses(r, rhorses(r) + m->horses); /* Was macht das denn hier? * Baumwanderung wird in trees() gemacht. - * wer fragt das? Die Baumwanderung war abhngig von der + * wer fragt das? Die Baumwanderung war abhängig von der * Auswertungsreihenfolge der regionen, - * das hatte ich gendert. jemand hat es wieder gelscht, toll. - * ich habe es wieder aktiviert, mu getestet werden. + * das hatte ich geändert. jemand hat es wieder gelöscht, toll. + * ich habe es wieder aktiviert, muss getestet werden. */ *hp = m->next; m->next = free_migrants; @@ -433,7 +421,7 @@ static void horses(region * r) horses = rhorses(r); if (horses > 0) { if (is_cursed(r->attribs, C_CURSED_BY_THE_GODS, 0)) { - rsethorses(r, (int)(horses * 0.9F)); + rsethorses(r, (int)(horses * 0.9)); } else if (maxhorses) { int i; @@ -445,7 +433,7 @@ static void horses(region * r) if (a_find(r->attribs, &at_horseluck)) growth *= 2; /* printf("Horses: <%d> %d -> ", growth, horses); */ - i = (int)(0.5F + (horses * 0.0001F) * growth); + i = (int)(0.5 + (horses * 0.0001) * growth); /* printf("%d\n", horses); */ rsethorses(r, horses + i); } @@ -454,8 +442,8 @@ static void horses(region * r) /* Pferde wandern in Nachbarregionen. * Falls die Nachbarregion noch berechnet - * werden mu, wird eine migration-Struktur gebildet, - * die dann erst in die Berechnung der Nachbarstruktur einfliet. + * werden muss, wird eine migration-Struktur gebildet, + * die dann erst in die Berechnung der Nachbarstruktur einfließt. */ for (n = 0; n != MAXDIRECTIONS; n++) { @@ -469,7 +457,7 @@ static void horses(region * r) else { migration *nb; /* haben wir die Migration schonmal benutzt? - * wenn nicht, mssen wir sie suchen. + * wenn nicht, müssen wir sie suchen. * Wandernde Pferde vermehren sich nicht. */ nb = get_migrants(r2); @@ -565,11 +553,11 @@ growing_trees(region * r, const int current_season, const int last_weeks_season) a = a_find(r->attribs, &at_germs); if (a && last_weeks_season == SEASON_SPRING) { - /* ungekeimte Samen bleiben erhalten, Sprlinge wachsen */ + /* ungekeimte Samen bleiben erhalten, Sprößlinge wachsen */ sprout = _min(a->data.sa[1], rtrees(r, 1)); - /* aus dem gesamt Sprlingepool abziehen */ + /* aus dem gesamt Sprößlingepool abziehen */ rsettrees(r, 1, rtrees(r, 1) - sprout); - /* zu den Bumen hinzufgen */ + /* zu den Bäumen hinzufügen */ rsettrees(r, 2, rtrees(r, 2) + sprout); a_removeall(&r->attribs, &at_germs); @@ -585,7 +573,7 @@ growing_trees(region * r, const int current_season, const int last_weeks_season) return; /* Grundchance 1.0% */ - /* Jeder Elf in der Region erhht die Chance marginal */ + /* Jeder Elf in der Region erhöht die Chance marginal */ elves = _min(elves, production(r) / 8); if (elves) { seedchance += 1.0 - pow(0.99999, elves * RESOURCE_QUANTITY); @@ -606,19 +594,19 @@ growing_trees(region * r, const int current_season, const int last_weeks_season) } } - /* Bume breiten sich in Nachbarregionen aus. */ + /* Bäume breiten sich in Nachbarregionen aus. */ /* Gesamtzahl der Samen: - * bis zu 6% (FORESTGROWTH*3) der Bume samen in die Nachbarregionen */ + * bis zu 6% (FORESTGROWTH*3) der Bäume samen in die Nachbarregionen */ seeds = (rtrees(r, 2) * FORESTGROWTH * 3) / 1000000; for (d = 0; d != MAXDIRECTIONS; ++d) { region *r2 = rconnect(r, d); if (r2 && fval(r2->terrain, LAND_REGION) && r2->terrain->size) { /* Eine Landregion, wir versuchen Samen zu verteilen: - * Die Chance, das Samen ein Stck Boden finden, in dem sie - * keimen knnen, hngt von der Bewuchsdichte und der - * verfgbaren Flche ab. In Gletschern gibt es weniger - * Mglichkeiten als in Ebenen. */ + * Die Chance, das Samen ein Stück Boden finden, in dem sie + * keimen können, hängt von der Bewuchsdichte und der + * verfügbaren Fläche ab. In Gletschern gibt es weniger + * Möglichkeiten als in Ebenen. */ sprout = 0; seedchance = (1000 * maxworkingpeasants(r2)) / r2->terrain->size; for (i = 0; i < seeds / MAXDIRECTIONS; i++) { @@ -635,8 +623,8 @@ growing_trees(region * r, const int current_season, const int last_weeks_season) if (is_cursed(r->attribs, C_CURSED_BY_THE_GODS, 0)) return; - /* in at_germs merken uns die Zahl der Samen und Sprlinge, die - * dieses Jahr lter werden drfen, damit nicht ein Same im selben + /* in at_germs merken uns die Zahl der Samen und Sprößlinge, die + * dieses Jahr älter werden dürfen, damit nicht ein Same im selben * Zyklus zum Baum werden kann */ a = a_find(r->attribs, &at_germs); if (!a) { @@ -644,13 +632,13 @@ growing_trees(region * r, const int current_season, const int last_weeks_season) a->data.sa[0] = (short)rtrees(r, 0); a->data.sa[1] = (short)rtrees(r, 1); } - /* wir haben 6 Wochen zum wachsen, jeder Same/Spro hat 18% Chance + /* wir haben 6 Wochen zum wachsen, jeder Same/Spross hat 18% Chance * zu wachsen, damit sollten nach 5-6 Wochen alle gewachsen sein */ growth = 1800; /* Samenwachstum */ - /* Raubbau abfangen, es drfen nie mehr Samen wachsen, als aktuell + /* Raubbau abfangen, es dürfen nie mehr Samen wachsen, als aktuell * in der Region sind */ seeds = _min(a->data.sa[0], rtrees(r, 0)); sprout = 0; @@ -663,15 +651,15 @@ growing_trees(region * r, const int current_season, const int last_weeks_season) a->data.sa[0] = (short)(seeds - sprout); /* aus dem gesamt Samenpool abziehen */ rsettrees(r, 0, rtrees(r, 0) - sprout); - /* zu den Sprlinge hinzufgen */ + /* zu den Sprößlinge hinzufügen */ rsettrees(r, 1, rtrees(r, 1) + sprout); /* Baumwachstum */ - /* hier gehen wir davon aus, das Jungbume nicht ohne weiteres aus - * der Region entfernt werden knnen, da Jungbume in der gleichen - * Runde nachwachsen, wir also nicht mehr zwischen diesjhrigen und - * 'alten' Jungbumen unterscheiden knnten */ + /* hier gehen wir davon aus, das Jungbäume nicht ohne weiteres aus + * der Region entfernt werden können, da Jungbäume in der gleichen + * Runde nachwachsen, wir also nicht mehr zwischen diesjährigen und + * 'alten' Jungbäumen unterscheiden könnten */ sprout = _min(a->data.sa[1], rtrees(r, 1)); grownup_trees = 0; @@ -679,11 +667,11 @@ growing_trees(region * r, const int current_season, const int last_weeks_season) if (rng_int() % 10000 < growth) grownup_trees++; } - /* aus dem Sprlingepool dieses Jahres abziehen */ + /* aus dem Sprößlingepool dieses Jahres abziehen */ a->data.sa[1] = (short)(sprout - grownup_trees); - /* aus dem gesamt Sprlingepool abziehen */ + /* aus dem gesamt Sprößlingepool abziehen */ rsettrees(r, 1, rtrees(r, 1) - grownup_trees); - /* zu den Bumen hinzufgen */ + /* zu den Bäumen hinzufügen */ rsettrees(r, 2, rtrees(r, 2) + grownup_trees); } } @@ -691,10 +679,10 @@ growing_trees(region * r, const int current_season, const int last_weeks_season) static void growing_herbs(region * r, const int current_season, const int last_weeks_season) { - /* Jetzt die Krutervermehrung. Vermehrt wird logistisch: + /* Jetzt die Kräutervermehrung. Vermehrt wird logistisch: * * Jedes Kraut hat eine Wahrscheinlichkeit von (100-(vorhandene - * Kruter))% sich zu vermehren. */ + * Kräuter))% sich zu vermehren. */ if (current_season != SEASON_WINTER) { int i; for (i = rherbs(r); i > 0; i--) { @@ -737,6 +725,45 @@ void immigration(void) } } +static void nmr_warnings(void) +{ + faction *f, *fa; +#define FRIEND (HELP_GUARD|HELP_MONEY) + for (f = factions; f; f = f->next) { + if (!fval(f, FFL_NOIDLEOUT) && turn > f->lastorders) { + ADDMSG(&f->msgs, msg_message("nmr_warning", "")); + if (turn - f->lastorders == NMRTimeout() - 1) { + ADDMSG(&f->msgs, msg_message("nmr_warning_final", "")); + } + if ((turn - f->lastorders) >= 2) { + message *msg = NULL; + for (fa = factions; fa; fa = fa->next) { + int warn = 0; + if (get_param_int(global.parameters, "rules.alliances", 0) != 0) { + if (f->alliance && f->alliance == fa->alliance) { + warn = 1; + } + } + else if (alliedfaction(NULL, f, fa, FRIEND) + && alliedfaction(NULL, fa, f, FRIEND)) { + warn = 1; + } + if (warn) { + if (msg == NULL) { + msg = + msg_message("warn_dropout", "faction turns", f, + turn - f->lastorders); + } + add_message(&fa->msgs, msg); + } + } + if (msg != NULL) + msg_release(msg); + } + } + } +} + void demographics(void) { region *r; @@ -812,7 +839,6 @@ void demographics(void) remove_empty_units(); immigration(); - checkorders(); } /* ------------------------------------------------------------- */ @@ -1072,7 +1098,7 @@ int enter_building(unit * u, order * ord, int id, bool report) region *r = u->region; building *b; - /* Schwimmer knnen keine Gebude betreten, auer diese sind + /* Schwimmer können keine Gebäude betreten, außer diese sind * auf dem Ozean */ if (!fval(u_race(u), RCF_WALK) && !fval(u_race(u), RCF_FLY)) { if (!fval(r->terrain, SEA_REGION)) { @@ -1188,8 +1214,8 @@ void do_enter(struct region *r, bool is_final_attempt) } if (ulast != NULL) { /* Wenn wir hier angekommen sind, war der Befehl - * erfolgreich und wir lschen ihn, damit er im - * zweiten Versuch nicht nochmal ausgefhrt wird. */ + * erfolgreich und wir löschen ihn, damit er im + * zweiten Versuch nicht nochmal ausgeführt wird. */ *ordp = ord->next; ord->next = NULL; free_order(ord); @@ -1321,10 +1347,12 @@ int ally_cmd(unit * u, struct order *ord) s = gettoken(token, sizeof(token)); - if (!s[0]) + if (!s || !s[0]) { keyword = P_ANY; - else + } + else { keyword = findparam(s, u->faction->locale); + } sfp = &u->faction->allies; if (fval(u, UFL_GROUP)) { @@ -1501,9 +1529,10 @@ int prefix_cmd(unit * u, struct order *ord) ap = &u->faction->attribs; if (fval(u, UFL_GROUP)) { attrib *a = a_find(u->attribs, &at_group); - group *g = (group *)a->data.v; - if (a) + if (a) { + group *g = (group *)a->data.v; ap = &g->attribs; + } } set_prefix(ap, race_prefixes[var.i]); } @@ -1739,10 +1768,11 @@ int name_cmd(struct unit *u, struct order *ord) } else { const struct locale *lang = locales; + size_t f_len = strlen(f->name); for (; lang; lang = nextlocale(lang)) { const char *fdname = LOC(lang, "factiondefault"); size_t fdlen = strlen(fdname); - if (strlen(f->name) >= fdlen && strncmp(f->name, fdname, fdlen) == 0) { + if (f_len >= fdlen && strncmp(f->name, fdname, fdlen) == 0) { break; } } @@ -1776,18 +1806,17 @@ int name_cmd(struct unit *u, struct order *ord) } else { const struct locale *lang = locales; + size_t sh_len = strlen(sh->name); for (; lang; lang = nextlocale(lang)) { const char *sdname = LOC(lang, sh->type->_name); size_t sdlen = strlen(sdname); - if (strlen(sh->name) >= sdlen - && strncmp(sh->name, sdname, sdlen) == 0) { + if (sh_len >= sdlen && strncmp(sh->name, sdname, sdlen) == 0) { break; } sdname = LOC(lang, parameters[P_SHIP]); sdlen = strlen(sdname); - if (strlen(sh->name) >= sdlen - && strncmp(sh->name, sdname, sdlen) == 0) { + if (sh_len >= sdlen && strncmp(sh->name, sdname, sdlen) == 0) { break; } @@ -1834,11 +1863,10 @@ int name_cmd(struct unit *u, struct order *ord) break; } else { - const char *udefault = LOC(u2->faction->locale, "unitdefault"); - size_t udlen = strlen(udefault); - size_t unlen = strlen(u2->name); - if (unlen >= udlen && strncmp(u2->name, udefault, udlen) != 0) { - cmistake(u2, ord, 244, MSG_EVENT); + char udefault[32]; + default_name(u2, udefault, sizeof(udefault)); + if (strcmp(unit_getname(u2), udefault) != 0) { + cmistake(u, ord, 244, MSG_EVENT); break; } } @@ -1850,10 +1878,10 @@ int name_cmd(struct unit *u, struct order *ord) ADDMSG(&u2->faction->msgs, msg_message("renamed_notseen", "renamed region", u2, r)); } - s = &u2->name; + s = &u2->_name; } else { - s = &u->name; + s = &u->_name; } break; @@ -1964,13 +1992,13 @@ int mail_cmd(unit * u, struct order *ord) s = gettoken(token, sizeof(token)); /* Falls kein Parameter, ist das eine Einheitsnummer; - * das Fllwort "AN" mu wegfallen, da gltige Nummer! */ + * das Füllwort "AN" muss wegfallen, da gültige Nummer! */ do { cont = 0; switch (findparam_ex(s, u->faction->locale)) { case P_REGION: - /* knnen alle Einheiten in der Region sehen */ + /* können alle Einheiten in der Region sehen */ s = getstrtoken(); if (!s || !s[0]) { cmistake(u, ord, 30, MSG_MESSAGE); @@ -2282,7 +2310,7 @@ static bool display_race(faction * f, unit * u, const race * rc) int a, at_count; char buf[2048], *bufp = buf; size_t size = sizeof(buf) - 1; - int bytes; + size_t bytes; if (u && u_race(u) != rc) return false; @@ -2298,7 +2326,7 @@ static bool display_race(faction * f, unit * u, const race * rc) info = LOC(f->locale, mkname("raceinfo", "no_info")); } - bytes = (int)strlcpy(bufp, info, size); + bytes = strlcpy(bufp, info, size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); @@ -2323,7 +2351,7 @@ static bool display_race(faction * f, unit * u, const race * rc) if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); - /* b_armor : Rstung */ + /* b_armor : Rüstung */ if (rc->armor > 0) { bytes = slprintf(bufp, size, ", %s: %d", LOC(f->locale, "stat_armor"), rc->armor); @@ -2340,56 +2368,56 @@ static bool display_race(faction * f, unit * u, const race * rc) /* b_damage : Schaden */ at_count = 0; - for (a = 0; a < 6; a++) { + for (a = 0; a < RACE_ATTACKS; a++) { if (rc->attack[a].type != AT_NONE) { at_count++; } } if (rc->battle_flags & BF_EQUIPMENT) { - bytes = _snprintf(bufp, size, " %s", LOC(f->locale, "stat_equipment")); + bytes = (size_t)_snprintf(bufp, size, " %s", LOC(f->locale, "stat_equipment")); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } if (rc->battle_flags & BF_RES_PIERCE) { - bytes = _snprintf(bufp, size, " %s", LOC(f->locale, "stat_pierce")); + bytes = (size_t)_snprintf(bufp, size, " %s", LOC(f->locale, "stat_pierce")); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } if (rc->battle_flags & BF_RES_CUT) { - bytes = _snprintf(bufp, size, " %s", LOC(f->locale, "stat_cut")); + bytes = (size_t)_snprintf(bufp, size, " %s", LOC(f->locale, "stat_cut")); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } if (rc->battle_flags & BF_RES_BASH) { - bytes = _snprintf(bufp, size, " %s", LOC(f->locale, "stat_bash")); + bytes = (size_t)_snprintf(bufp, size, " %s", LOC(f->locale, "stat_bash")); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } bytes = - _snprintf(bufp, size, " %d %s", at_count, LOC(f->locale, + (size_t)_snprintf(bufp, size, " %d %s", at_count, LOC(f->locale, (at_count == 1) ? "stat_attack" : "stat_attacks")); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); - for (a = 0; a < 6; a++) { + for (a = 0; a < RACE_ATTACKS; a++) { if (rc->attack[a].type != AT_NONE) { if (a != 0) - bytes = (int)strlcpy(bufp, ", ", size); + bytes = strlcpy(bufp, ", ", size); else - bytes = (int)strlcpy(bufp, ": ", size); + bytes = strlcpy(bufp, ": ", size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); switch (rc->attack[a].type) { case AT_STANDARD: bytes = - _snprintf(bufp, size, "%s (%s)", + (size_t)_snprintf(bufp, size, "%s (%s)", LOC(f->locale, "attack_standard"), rc->def_damage); break; case AT_NATURAL: bytes = - _snprintf(bufp, size, "%s (%s)", + (size_t)_snprintf(bufp, size, "%s (%s)", LOC(f->locale, "attack_natural"), rc->attack[a].data.dice); break; case AT_SPELL: @@ -2397,11 +2425,11 @@ static bool display_race(faction * f, unit * u, const race * rc) case AT_DRAIN_ST: case AT_DRAIN_EXP: case AT_DAZZLE: - bytes = _snprintf(bufp, size, "%s", LOC(f->locale, "attack_magical")); + bytes = (size_t)_snprintf(bufp, size, "%s", LOC(f->locale, "attack_magical")); break; case AT_STRUCTURAL: bytes = - _snprintf(bufp, size, "%s (%s)", + (size_t)_snprintf(bufp, size, "%s (%s)", LOC(f->locale, "attack_structural"), rc->attack[a].data.dice); break; default: @@ -2545,7 +2573,7 @@ int origin_cmd(unit * u, struct order *ord) px = (short)getint(); py = (short)getint(); - set_ursprung(u->faction, getplaneid(u->region), px, py); + faction_setorigin(u->faction, getplaneid(u->region), px, py); return 0; } @@ -2634,7 +2662,7 @@ int combatspell_cmd(unit * u, struct order *ord) init_order(ord); s = gettoken(token, sizeof(token)); - /* KAMPFZAUBER [NICHT] lscht alle gesetzten Kampfzauber */ + /* KAMPFZAUBER [NICHT] löscht alle gesetzten Kampfzauber */ if (!s || *s == 0 || findparam(s, u->faction->locale) == P_NOT) { unset_combatspell(u, 0); return 0; @@ -2642,7 +2670,7 @@ int combatspell_cmd(unit * u, struct order *ord) /* Optional: STUFE n */ if (findparam(s, u->faction->locale) == P_LEVEL) { - /* Merken, setzen kommt erst spter */ + /* Merken, setzen kommt erst später */ level = getint(); level = _max(0, level); s = gettoken(token, sizeof(token)); @@ -2657,7 +2685,7 @@ int combatspell_cmd(unit * u, struct order *ord) s = gettoken(token, sizeof(token)); if (findparam(s, u->faction->locale) == P_NOT) { - /* KAMPFZAUBER "" NICHT lscht diesen speziellen + /* KAMPFZAUBER "" NICHT löscht diesen speziellen * Kampfzauber */ unset_combatspell(u, sp); return 0; @@ -2672,13 +2700,13 @@ int combatspell_cmd(unit * u, struct order *ord) /* ------------------------------------------------------------- */ /* Beachten: einige Monster sollen auch unbewaffent die Region bewachen - * knnen */ + * können */ enum { E_GUARD_OK, E_GUARD_UNARMED, E_GUARD_NEWBIE, E_GUARD_FLEEING }; static int can_start_guarding(const unit * u) { - if (u->status >= ST_FLEE) + if (u->status >= ST_FLEE || fval(u, UFL_FLEEING)) return E_GUARD_FLEEING; if (fval(u_race(u), RCF_UNARMEDGUARD)) return E_GUARD_OK; @@ -2715,12 +2743,15 @@ void update_guards(void) int guard_on_cmd(unit * u, struct order *ord) { assert(getkeyword(ord) == K_GUARD); + assert(u); + assert(u->faction); init_order(ord); /* GUARD NOT is handled in goard_off_cmd earlier in the turn */ - if (getparam(u->faction->locale) == P_NOT) + if (getparam(u->faction->locale) == P_NOT) { return 0; + } if (fval(u->region->terrain, SEA_REGION)) { cmistake(u, ord, 2, MSG_EVENT); @@ -2734,7 +2765,7 @@ int guard_on_cmd(unit * u, struct order *ord) cmistake(u, ord, 95, MSG_EVENT); } else { - /* Monster der Monsterpartei drfen immer bewachen */ + /* Monster der Monsterpartei dürfen immer bewachen */ if (is_monsters(u->faction)) { guard(u, GUARD_ALL); } @@ -2768,7 +2799,7 @@ void sinkships(struct region * r) if (!sh->type->construction || sh->size >= sh->type->construction->maxsize) { if (fval(r->terrain, SEA_REGION) && (!enoughsailors(sh, r) || get_captain(sh) == NULL)) { - /* Schiff nicht seetchtig */ + /* Schiff nicht seetüchtig */ float dmg = get_param_flt(global.parameters, "rules.ship.damage.nocrewocean", 0.30F); @@ -2897,7 +2928,7 @@ void restack_units(void) cmistake(u, ord, 260, MSG_EVENT); } else if (v == u) { - cmistake(u, ord, 10, MSG_EVENT); + syntax_error(u, ord); } else { switch (p) { @@ -3093,7 +3124,7 @@ static building *age_building(building * b) * find out if there's a magician in there. */ for (u = r->units; u; u = u->next) { if (b == u->building && inside_building(u)) { - if (!(u_race(u)->ec_flags & GIVEITEM) == 0) { + if ((u_race(u)->ec_flags & ECF_KEEP_ITEM) == 0) { int n, unicorns = 0; for (n = 0; n != u->number; ++n) { if (chance(0.02)) { @@ -3131,7 +3162,7 @@ static building *age_building(building * b) else if (mage != NULL) { int sk = effskill(mage, SK_MAGIC); c->duration = _max(c->duration, sk / 2); - c->vigour = _max(c->vigour, sk); + c->vigour = _max(c->vigour, (float)sk); } } } @@ -3225,7 +3256,7 @@ static void ageing(void) sp = &(*sp)->next; } - /* Gebude */ + /* Gebäude */ for (bp = &r->buildings; *bp;) { building *b = *bp; age_building(b); @@ -3349,7 +3380,7 @@ void new_units(void) } u2 = create_unit(r, u->faction, 0, u->faction->race, alias, name, u); if (name != NULL) - free(name); + free(name); // TODO: use a buffer on the stack instead? fset(u2, UFL_ISNEW); a_add(&u2->attribs, a_new(&at_alias))->data.i = alias; @@ -3378,132 +3409,106 @@ void new_units(void) } } -/** Checks for two long orders and issues a warning if necessary. - */ -void check_long_orders(unit * u) +void update_long_order(unit * u) { order *ord; - keyword_t otherorder = MAXKEYWORDS; + bool exclusive = true; + keyword_t thiskwd = NOKEYWORD; + bool hunger = LongHunger(u); + freset(u, UFL_MOVED); + freset(u, UFL_LONGACTION); + + /* check all orders for a potential new long order this round: */ for (ord = u->orders; ord; ord = ord->next) { - if (getkeyword(ord) == NOKEYWORD) { - cmistake(u, ord, 22, MSG_EVENT); + keyword_t kwd = getkeyword(ord); + if (kwd == NOKEYWORD) continue; + + if (u->old_orders && is_repeated(kwd)) { + /* this new order will replace the old defaults */ + free_orders(&u->old_orders); } - else if (is_long(ord)) { - keyword_t longorder = getkeyword(ord); - if (otherorder != MAXKEYWORDS) { - switch (longorder) { + + // hungry units do not get long orders: + if (hunger) { + if (u->old_orders) { + // keep looking for repeated orders that might clear the old_orders + continue; + } + break; + } + + if (is_long(kwd)) { + if (thiskwd == NOKEYWORD) { + // we have found the (first) long order + // some long orders can have multiple instances: + switch (kwd) { + /* Wenn gehandelt wird, darf kein langer Befehl ausgeführt + * werden. Da Handel erst nach anderen langen Befehlen kommt, + * muss das vorher abgefangen werden. Wir merken uns also + * hier, ob die Einheit handelt. */ + case K_BUY: + case K_SELL: case K_CAST: - if (otherorder != longorder) { + // non-exclusive orders can be used with others. BUY can be paired with SELL, + // CAST with other CAST orders. compatibility is checked once the second + // long order is analyzed (below). + exclusive = false; + break; + + default: + set_order(&u->thisorder, copy_order(ord)); + break; + } + thiskwd = kwd; + } + else { + // we have found a second long order. this is okay for some, but not all commands. + // u->thisorder is already set, and should not have to be updated. + switch (kwd) { + case K_CAST: + if (thiskwd != K_CAST) { + cmistake(u, ord, 52, MSG_EVENT); + } + break; + case K_SELL: + if (thiskwd != K_SELL && thiskwd != K_BUY) { cmistake(u, ord, 52, MSG_EVENT); } break; case K_BUY: - if (otherorder == K_SELL) { - otherorder = K_BUY; + if (thiskwd != K_SELL) { + cmistake(u, ord, 52, MSG_EVENT); + } + else { + thiskwd = K_BUY; + } + break; + default: + // TODO: decide https://bugs.eressea.de/view.php?id=2080#c6011 + if (kwd > thiskwd) { + // swap out thisorder for the new one + cmistake(u, u->thisorder, 52, MSG_EVENT); + set_order(&u->thisorder, copy_order(ord)); } else { cmistake(u, ord, 52, MSG_EVENT); } break; - case K_SELL: - if (otherorder != K_SELL && otherorder != K_BUY) { - cmistake(u, ord, 52, MSG_EVENT); - } - break; - default: - cmistake(u, ord, 52, MSG_EVENT); } } - else { - otherorder = longorder; - } } } -} - -void update_long_order(unit * u) -{ - order *ord; - bool trade = false; - bool hunger = LongHunger(u); - - freset(u, UFL_MOVED); - freset(u, UFL_LONGACTION); if (hunger) { - /* Hungernde Einheiten fhren NUR den default-Befehl aus */ + // Hungernde Einheiten führen NUR den default-Befehl aus set_order(&u->thisorder, default_order(u->faction->locale)); - } - else { - check_long_orders(u); - } - /* check all orders for a potential new long order this round: */ - for (ord = u->orders; ord; ord = ord->next) { - if (getkeyword(ord) == NOKEYWORD) - continue; - - if (u->old_orders && is_repeated(ord)) { - /* this new order will replace the old defaults */ - free_orders(&u->old_orders); - if (hunger) - break; - } - if (hunger) - continue; - - if (is_exclusive(ord)) { - /* ber dieser Zeile nur Befehle, die auch eine idle Faction machen darf */ - if (idle(u->faction)) { - set_order(&u->thisorder, default_order(u->faction->locale)); - } - else { - set_order(&u->thisorder, copy_order(ord)); - } - break; - } - else { - keyword_t keyword = getkeyword(ord); - switch (keyword) { - /* Wenn gehandelt wird, darf kein langer Befehl ausgefhrt - * werden. Da Handel erst nach anderen langen Befehlen kommt, - * mu das vorher abgefangen werden. Wir merken uns also - * hier, ob die Einheit handelt. */ - case K_BUY: - case K_SELL: - /* Wenn die Einheit handelt, mu der Default-Befehl gelscht - * werden. - * Wird je diese Ausschliesslichkeit aufgehoben, muss man aufpassen - * mit der Reihenfolge von Kaufen, Verkaufen etc., damit es Spielern - * nicht moeglich ist, Schulden zu machen. */ - trade = true; - break; - - case K_CAST: - /* dient dazu, das neben Zaubern kein weiterer Befehl - * ausgefhrt werden kann, Zaubern ist ein kurzer Befehl */ - set_order(&u->thisorder, copy_order(ord)); - break; - - default: - break; - } - } - } - - if (hunger) { - return; - } - /* Wenn die Einheit handelt, mu der Default-Befehl gelscht - * werden. */ - - if (trade) { - /* fset(u, UFL_LONGACTION|UFL_NOTMOVING); */ + } else if (!exclusive) { + // Wenn die Einheit handelt oder zaubert, muss der Default-Befehl gelöscht werden. set_order(&u->thisorder, NULL); } } -static int -use_item(unit * u, const item_type * itype, int amount, struct order *ord) +static int use_item(unit * u, const item_type * itype, int amount, struct order *ord) { int i; int target = read_unitid(u->faction, u->region); @@ -3511,6 +3516,7 @@ use_item(unit * u, const item_type * itype, int amount, struct order *ord) i = get_pooled(u, itype->rtype, GET_DEFAULT, amount); if (amount > i) { + /* TODO: message? eg. "not enough %, using only %" */ amount = i; } if (amount == 0) { @@ -3518,10 +3524,15 @@ use_item(unit * u, const item_type * itype, int amount, struct order *ord) } if (target == -1) { + int result; if (itype->use == NULL) { return EUNUSABLE; } - return itype->use(u, itype, amount, ord); + result = itype->use ? itype->use(u, itype, amount, ord) : EUNUSABLE; + if (result>0) { + use_pooled(u, itype->rtype, GET_DEFAULT, result); + } + return result; } else { if (itype->useonother == NULL) { @@ -3564,7 +3575,7 @@ void monthly_healing(void) double healingcurse = 0; if (heal_ct != NULL) { - /* bonus zurcksetzen */ + /* bonus zurücksetzen */ curse *c = get_curse(r->attribs, heal_ct); if (c != NULL) { healingcurse = curse_geteffect(c); @@ -3574,8 +3585,8 @@ void monthly_healing(void) int umhp = unit_max_hp(u) * u->number; double p = 1.0; - /* hp ber Maximum bauen sich ab. Wird zb durch Elixier der Macht - * oder verndertes Ausdauertalent verursacht */ + /* hp über Maximum bauen sich ab. Wird zb durch Elixier der Macht + * oder verändertes Ausdauertalent verursacht */ if (u->hp > umhp) { u->hp -= (int)ceil((u->hp - umhp) / 2.0); if (u->hp < umhp) @@ -3602,7 +3613,7 @@ void monthly_healing(void) if (btype == bt_find("inn")) { p *= 1.5; } - /* pro punkt 5% hher */ + /* pro punkt 5% höher */ p *= (1.0 + healingcurse * 0.05); maxheal = p * maxheal; @@ -3614,7 +3625,7 @@ void monthly_healing(void) /* Aufaddieren der geheilten HP. */ u->hp = _min(u->hp + addhp, umhp); - /* soll man an negativer regeneration sterben knnen? */ + /* soll man an negativer regeneration sterben können? */ assert(u->hp > 0); } } @@ -3661,7 +3672,8 @@ void defaultorders(void) ord->next = NULL; free_order(ord); if (!neworders) { - /* lange Befehle aus orders und old_orders lschen zu gunsten des neuen */ + /* lange Befehle aus orders und old_orders löschen zu gunsten des neuen */ + // TODO: why only is_exclusive, not is_long? what about CAST, BUY, SELL? remove_exclusive(&u->orders); remove_exclusive(&u->old_orders); neworders = true; @@ -3770,6 +3782,10 @@ int use_cmd(unit * u, struct order *ord) init_order(ord); t = gettoken(token, sizeof(token)); + if (!t) { + cmistake(u, ord, 43, MSG_PRODUCE); + return err; + } n = atoi((const char *)t); if (n == 0) { if (isparam(t, u->faction->locale, P_ANY)) { @@ -3790,10 +3806,6 @@ int use_cmd(unit * u, struct order *ord) if (itype != NULL) { err = use_item(u, itype, n, ord); - assert(err <= 0 || !"use_item should not return positive values."); - if (err > 0) { - log_error("use_item returned a value>0 for %s\n", resourcename(itype->rtype, 0)); - } } switch (err) { case ENOITEM: @@ -3805,6 +3817,9 @@ int use_cmd(unit * u, struct order *ord) case ENOSKILL: cmistake(u, ord, 50, MSG_PRODUCE); break; + default: + // no error + break; } return err; } @@ -3912,24 +3927,27 @@ int claim_cmd(unit * u, struct order *ord) { char token[128]; const char *t; - int n; - const item_type *itype; + int n = 1; + const item_type *itype = 0; init_order(ord); t = gettoken(token, sizeof(token)); - n = atoi((const char *)t); - if (n == 0) { - n = 1; + if (t) { + n = atoi((const char *)t); + if (n == 0) { + n = 1; + } + else { + t = gettoken(token, sizeof(token)); + } + if (t) { + itype = finditemtype(t, u->faction->locale); + } } - else { - t = gettoken(token, sizeof(token)); - } - itype = finditemtype(t, u->faction->locale); - - if (itype != NULL) { + if (itype) { item **iclaim = i_find(&u->faction->items, itype); - if (iclaim != NULL && *iclaim != NULL) { + if (iclaim && *iclaim) { n = _min(n, (*iclaim)->number); i_change(iclaim, itype, -n); i_change(&u->items, itype, n); @@ -4303,34 +4321,17 @@ static void enter_2(region * r) do_enter(r, 1); } -static bool help_enter(unit *uo, unit *u) { +bool help_enter(unit *uo, unit *u) { return uo->faction == u->faction || alliedunit(uo, u->faction, HELP_GUARD); } -void force_leave(region *r) { - unit *u; - for (u = r->units; u; u = u->next) { - unit *uo = NULL; - if (u->building) { - uo = building_owner(u->building); - } - if (u->ship && r->land) { - uo = ship_owner(u->ship); - } - if (uo && !help_enter(uo, u)) { - message *msg = NULL; - if (u->building) { - msg = msg_message("force_leave_building", "unit owner building", u, uo, u->building); - } - else { - msg = msg_message("force_leave_ship", "unit owner ship", u, uo, u->ship); - } - if (msg) { - ADDMSG(&u->faction->msgs, msg); - } - leave(u, false); - } - } +static void do_force_leave(region *r) { + force_leave(r, NULL); +} + +bool rule_force_leave(int flags) { + int rules = get_param_int(global.parameters, "rules.owners.force_leave", 0); + return (rules&flags) == flags; } static void maintain_buildings_1(region * r) @@ -4369,7 +4370,14 @@ void init_processor(void) { int p; + while (processors) { + processor * next = processors->next; + free(processors); + processors = next; + } + p = 10; + add_proc_global(p, nmr_warnings, "NMR Warnings"); add_proc_global(p, new_units, "Neue Einheiten erschaffen"); p += 10; @@ -4381,17 +4389,17 @@ void init_processor(void) add_proc_order(p, K_GROUP, group_cmd, 0, NULL); p += 10; - add_proc_order(p, K_QUIT, &quit_cmd, 0, NULL); -// add_proc_order(p, K_URSPRUNG, &origin_cmd, 0, NULL); - add_proc_order(p, K_ALLY, &ally_cmd, 0, NULL); - add_proc_order(p, K_PREFIX, &prefix_cmd, 0, NULL); - add_proc_order(p, K_SETSTEALTH, &setstealth_cmd, 0, NULL); - add_proc_order(p, K_STATUS, &status_cmd, 0, NULL); - add_proc_order(p, K_COMBATSPELL, &combatspell_cmd, 0, NULL); - add_proc_order(p, K_DISPLAY, &display_cmd, 0, NULL); - add_proc_order(p, K_NAME, &name_cmd, 0, NULL); - add_proc_order(p, K_GUARD, &guard_off_cmd, 0, NULL); - add_proc_order(p, K_RESHOW, &reshow_cmd, 0, NULL); + add_proc_order(p, K_QUIT, quit_cmd, 0, NULL); + add_proc_order(p, K_URSPRUNG, origin_cmd, 0, NULL); + add_proc_order(p, K_ALLY, ally_cmd, 0, NULL); + add_proc_order(p, K_PREFIX, prefix_cmd, 0, NULL); + add_proc_order(p, K_SETSTEALTH, setstealth_cmd, 0, NULL); + add_proc_order(p, K_STATUS, status_cmd, 0, NULL); + add_proc_order(p, K_COMBATSPELL, combatspell_cmd, 0, NULL); + add_proc_order(p, K_DISPLAY, display_cmd, 0, NULL); + add_proc_order(p, K_NAME, name_cmd, 0, NULL); + add_proc_order(p, K_GUARD, guard_off_cmd, 0, NULL); + add_proc_order(p, K_RESHOW, reshow_cmd, 0, NULL); if (get_param_int(global.parameters, "rules.alliances", 0) == 1) { p += 10; @@ -4403,7 +4411,7 @@ void init_processor(void) add_proc_order(p, K_MAIL, mail_cmd, 0, "Botschaften"); p += 10; /* all claims must be done before we can USE */ - add_proc_region(p, &enter_1, "Betreten (1. Versuch)"); /* for GIVE CONTROL */ + add_proc_region(p, enter_1, "Betreten (1. Versuch)"); /* for GIVE CONTROL */ add_proc_order(p, K_USE, use_cmd, 0, "Benutzen"); p += 10; /* in case it has any effects on alliance victories */ @@ -4426,25 +4434,25 @@ void init_processor(void) p += 10; /* can't allow reserve before siege (weapons) */ add_proc_region(p, enter_1, "Betreten (3. Versuch)"); /* to claim a castle after a victory and to be able to DESTROY it in the same turn */ if (get_param_int(global.parameters, "rules.reserve.twophase", 0)) { - add_proc_order(p, K_RESERVE, &reserve_self, 0, "RESERVE (self)"); + add_proc_order(p, K_RESERVE, reserve_self, 0, "RESERVE (self)"); p += 10; } - add_proc_order(p, K_RESERVE, &reserve_cmd, 0, "RESERVE (all)"); - add_proc_order(p, K_CLAIM, &claim_cmd, 0, NULL); + add_proc_order(p, K_RESERVE, reserve_cmd, 0, "RESERVE (all)"); + add_proc_order(p, K_CLAIM, claim_cmd, 0, NULL); add_proc_unit(p, follow_unit, "Folge auf Einheiten setzen"); p += 10; /* rest rng again before economics */ - if (get_param_int(global.parameters, "rules.owners.force_leave", 0)) { - add_proc_region(p, force_leave, "kick non-allies out of buildings/ships"); + if (rule_force_leave(FORCE_LEAVE_ALL)) { + add_proc_region(p, do_force_leave, "kick non-allies out of buildings/ships"); } add_proc_region(p, economics, "Zerstoeren, Geben, Rekrutieren, Vergessen"); - add_proc_order(p, K_PROMOTION, &promotion_cmd, 0, "Heldenbefoerderung"); + add_proc_order(p, K_PROMOTION, promotion_cmd, 0, "Heldenbefoerderung"); p += 10; if (!keyword_disabled(K_PAY)) { - add_proc_order(p, K_PAY, &pay_cmd, 0, "Gebaeudeunterhalt (disable)"); + add_proc_order(p, K_PAY, pay_cmd, 0, "Gebaeudeunterhalt (disable)"); } - add_proc_postregion(p, &maintain_buildings_1, + add_proc_postregion(p, maintain_buildings_1, "Gebaeudeunterhalt (1. Versuch)"); p += 10; /* QUIT fuer sich alleine */ @@ -4452,79 +4460,75 @@ void init_processor(void) if (!keyword_disabled(K_CAST)) { p += 10; - add_proc_global(p, &magic, "Zaubern"); + add_proc_global(p, magic, "Zaubern"); } p += 10; - add_proc_order(p, K_TEACH, &teach_cmd, PROC_THISORDER | PROC_LONGORDER, + add_proc_order(p, K_TEACH, teach_cmd, PROC_THISORDER | PROC_LONGORDER, "Lehren"); p += 10; - add_proc_order(p, K_STUDY, &learn_cmd, PROC_THISORDER | PROC_LONGORDER, + add_proc_order(p, K_STUDY, learn_cmd, PROC_THISORDER | PROC_LONGORDER, "Lernen"); p += 10; - add_proc_order(p, K_MAKE, &make_cmd, PROC_THISORDER | PROC_LONGORDER, + add_proc_order(p, K_MAKE, make_cmd, PROC_THISORDER | PROC_LONGORDER, "Produktion"); - add_proc_postregion(p, &produce, "Arbeiten, Handel, Rekruten"); - add_proc_postregion(p, &split_allocations, "Produktion II"); + add_proc_postregion(p, produce, "Arbeiten, Handel, Rekruten"); + add_proc_postregion(p, split_allocations, "Produktion II"); p += 10; - add_proc_region(p, &enter_2, "Betreten (4. Versuch)"); /* Once again after QUIT */ + add_proc_region(p, enter_2, "Betreten (4. Versuch)"); /* Once again after QUIT */ p += 10; - add_proc_region(p, &sinkships, "Schiffe sinken"); + add_proc_region(p, sinkships, "Schiffe sinken"); p += 10; - add_proc_global(p, &movement, "Bewegungen"); + add_proc_global(p, movement, "Bewegungen"); if (get_param_int(global.parameters, "work.auto", 0)) { p += 10; - add_proc_region(p, &auto_work, "Arbeiten (auto)"); + add_proc_region(p, auto_work, "Arbeiten (auto)"); } p += 10; - add_proc_order(p, K_GUARD, &guard_on_cmd, 0, "Bewache (an)"); + add_proc_order(p, K_GUARD, guard_on_cmd, 0, "Bewache (an)"); if (get_param_int(global.parameters, "rules.encounters", 0)) { p += 10; - add_proc_global(p, &encounters, "Zufallsbegegnungen"); + add_proc_global(p, encounters, "Zufallsbegegnungen"); } p += 10; - add_proc_unit(p, &monster_kills_peasants, + add_proc_unit(p, monster_kills_peasants, "Monster fressen und vertreiben Bauern"); p += 10; - add_proc_global(p, &randomevents, "Zufallsereignisse"); + add_proc_global(p, randomevents, "Zufallsereignisse"); p += 10; - add_proc_global(p, &monthly_healing, "Regeneration (HP)"); - add_proc_global(p, ®enerate_aura, "Regeneration (Aura)"); + add_proc_global(p, monthly_healing, "Regeneration (HP)"); + add_proc_global(p, regenerate_aura, "Regeneration (Aura)"); if (!keyword_disabled(K_DEFAULT)) { - add_proc_global(p, &defaultorders, "Defaults setzen"); + add_proc_global(p, defaultorders, "Defaults setzen"); } - add_proc_global(p, &demographics, "Nahrung, Seuchen, Wachstum, Wanderung"); + add_proc_global(p, demographics, "Nahrung, Seuchen, Wachstum, Wanderung"); if (!keyword_disabled(K_SORT)) { p += 10; add_proc_global(p, restack_units, "Einheiten sortieren"); } if (!keyword_disabled(K_NUMBER)) { - add_proc_order(p, K_NUMBER, &renumber_cmd, 0, "Neue Nummern (Einheiten)"); + add_proc_order(p, K_NUMBER, renumber_cmd, 0, "Neue Nummern (Einheiten)"); p += 10; - add_proc_global(p, &renumber_factions, "Neue Nummern"); + add_proc_global(p, renumber_factions, "Neue Nummern"); } } void processorders(void) { - static int init = 0; + init_processor(); - if (!init) { - init_processor(); - init = 1; - } update_spells(); process(); /*************************************************/ @@ -4542,8 +4546,8 @@ void processorders(void) wormholes_update(); } - /* immer ausfhren, wenn neue Sprche dazugekommen sind, oder sich - * Beschreibungen gendert haben */ + /* immer ausführen, wenn neue Sprüche dazugekommen sind, oder sich + * Beschreibungen geändert haben */ update_spells(); warn_password(); } diff --git a/src/laws.h b/src/laws.h index 4f4188448..7eec612e3 100755 --- a/src/laws.h +++ b/src/laws.h @@ -105,9 +105,13 @@ extern "C" { bool seefaction(const struct faction *f, const struct region *r, const struct unit *u, int modifier); int armedmen(const struct unit *u, bool siege_weapons); - void force_leave(struct region *r); int peasant_luck_effect(int peasants, int luck, int maxp, double variance); + #define FORCE_LEAVE_POSTCOMBAT 1 + #define FORCE_LEAVE_ALL 2 + bool rule_force_leave(int flag); + bool help_enter(struct unit *uo, struct unit *u); + #ifdef __cplusplus } #endif diff --git a/src/laws.test.c b/src/laws.test.c index 0b2d2dddc..0c4881c85 100644 --- a/src/laws.test.c +++ b/src/laws.test.c @@ -1,5 +1,7 @@ #include #include "laws.h" +#include "battle.h" +#include "monster.h" #include #include @@ -230,6 +232,21 @@ static void test_display_cmd(CuTest *tc) { test_cleanup(); } +static void test_rule_force_leave(CuTest *tc) { + set_param(&global.parameters, "rules.owners.force_leave", "0"); + CuAssertIntEquals(tc, false, rule_force_leave(FORCE_LEAVE_ALL)); + CuAssertIntEquals(tc, false, rule_force_leave(FORCE_LEAVE_POSTCOMBAT)); + set_param(&global.parameters, "rules.owners.force_leave", "1"); + CuAssertIntEquals(tc, false, rule_force_leave(FORCE_LEAVE_ALL)); + CuAssertIntEquals(tc, true, rule_force_leave(FORCE_LEAVE_POSTCOMBAT)); + set_param(&global.parameters, "rules.owners.force_leave", "2"); + CuAssertIntEquals(tc, true, rule_force_leave(FORCE_LEAVE_ALL)); + CuAssertIntEquals(tc, false, rule_force_leave(FORCE_LEAVE_POSTCOMBAT)); + set_param(&global.parameters, "rules.owners.force_leave", "3"); + CuAssertIntEquals(tc, true, rule_force_leave(FORCE_LEAVE_ALL)); + CuAssertIntEquals(tc, true, rule_force_leave(FORCE_LEAVE_POSTCOMBAT)); +} + static void test_force_leave_buildings(CuTest *tc) { ally *al; region *r; @@ -246,8 +263,8 @@ static void test_force_leave_buildings(CuTest *tc) { building_set_owner(u1); u_set_building(u2, b); u_set_building(u3, b); - force_leave(r); - CuAssertPtrEquals_Msg(tc, "owner should not be forecd to leave", b, u1->building); + force_leave(r, NULL); + CuAssertPtrEquals_Msg(tc, "owner should not be forced to leave", b, u1->building); CuAssertPtrEquals_Msg(tc, "same faction should not be forced to leave", b, u2->building); CuAssertPtrEquals_Msg(tc, "non-allies should be forced to leave", NULL, u3->building); msg = test_get_last_message(u3->faction->msgs); @@ -256,7 +273,7 @@ static void test_force_leave_buildings(CuTest *tc) { u_set_building(u3, b); al = ally_add(&u1->faction->allies, u3->faction); al->status = HELP_GUARD; - force_leave(r); + force_leave(r, NULL); CuAssertPtrEquals_Msg(tc, "allies should not be forced to leave", b, u3->building); test_cleanup(); } @@ -274,7 +291,7 @@ static void test_force_leave_ships(CuTest *tc) { u_set_ship(u1, sh); u_set_ship(u2, sh); ship_set_owner(u1); - force_leave(r); + force_leave(r, NULL); CuAssertPtrEquals_Msg(tc, "non-allies should be forced to leave", NULL, u2->ship); msg = test_get_last_message(u2->faction->msgs); CuAssertStrEquals(tc, "force_leave_ship", test_get_messagetype(msg)); @@ -293,7 +310,7 @@ static void test_force_leave_ships_on_ocean(CuTest *tc) { u_set_ship(u1, sh); u_set_ship(u2, sh); ship_set_owner(u1); - force_leave(r); + force_leave(r, NULL); CuAssertPtrEquals_Msg(tc, "no forcing out of ships on oceans", sh, u2->ship); test_cleanup(); } @@ -696,12 +713,11 @@ static void test_reserve_self(CuTest *tc) { static void statistic_test(CuTest *tc, int peasants, int luck, int maxp, double variance, int min_value, int max_value) { - int effect, i; - for (i = 0; i < 1000; ++i) { - effect = peasant_luck_effect(peasants, luck, maxp, variance); - CuAssertTrue(tc, min_value <= effect); - CuAssertTrue(tc, max_value >= effect); - } + int effect; + + effect = peasant_luck_effect(peasants, luck, maxp, variance); + CuAssertTrue(tc, min_value <= effect); + CuAssertTrue(tc, max_value >= effect); } static void test_peasant_luck_effect(CuTest *tc) { @@ -713,8 +729,11 @@ static void test_peasant_luck_effect(CuTest *tc) { statistic_test(tc, 100, 0, 1000, 0, 0, 0); statistic_test(tc, 100, 2, 1000, 0, 1, 1); +/* statistic_test(tc, 1000, 400, 1000, 0, (int)(400 * 10 * 0.001 * .75), (int)(400 * 10 * 0.001 * .75)); + */ + statistic_test(tc, 1000, 400, 1000, 0, 3, 3); statistic_test(tc, 1000, 1000, 2000, .5, 1, 501); set_param(&global.parameters, "rules.peasants.growth.factor", "1"); @@ -750,9 +769,225 @@ static void test_luck_message(CuTest *tc) { test_cleanup(); } +static void test_long_order_normal(CuTest *tc) { + // TODO: write more tests + unit *u; + order *ord; + test_cleanup(); + u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0)); + fset(u, UFL_MOVED); + fset(u, UFL_LONGACTION); + u->faction->locale = get_or_create_locale("de"); + ord = create_order(K_MOVE, u->faction->locale, 0); + unit_addorder(u, ord); + update_long_order(u); + CuAssertPtrEquals(tc, ord->data, u->thisorder->data); + CuAssertIntEquals(tc, 0, fval(u, UFL_MOVED)); + CuAssertIntEquals(tc, 0, fval(u, UFL_LONGACTION)); + CuAssertPtrNotNull(tc, u->orders); + CuAssertPtrEquals(tc, 0, u->faction->msgs); + CuAssertPtrEquals(tc, 0, u->old_orders); + test_cleanup(); +} + +static void test_long_order_none(CuTest *tc) { + // TODO: write more tests + unit *u; + test_cleanup(); + u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0)); + u->faction->locale = get_or_create_locale("de"); + update_long_order(u); + CuAssertPtrEquals(tc, 0, u->thisorder); + CuAssertPtrEquals(tc, 0, u->orders); + CuAssertPtrEquals(tc, 0, u->faction->msgs); + test_cleanup(); +} + +static void test_long_order_cast(CuTest *tc) { + // TODO: write more tests + unit *u; + test_cleanup(); + u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0)); + u->faction->locale = get_or_create_locale("de"); + unit_addorder(u, create_order(K_CAST, u->faction->locale, 0)); + unit_addorder(u, create_order(K_CAST, u->faction->locale, 0)); + update_long_order(u); + CuAssertPtrEquals(tc, 0, u->thisorder); + CuAssertPtrNotNull(tc, u->orders); + CuAssertPtrEquals(tc, 0, u->faction->msgs); + test_cleanup(); +} + +static void test_long_order_buy_sell(CuTest *tc) { + // TODO: write more tests + unit *u; + test_cleanup(); + u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0)); + u->faction->locale = get_or_create_locale("de"); + unit_addorder(u, create_order(K_BUY, u->faction->locale, 0)); + unit_addorder(u, create_order(K_SELL, u->faction->locale, 0)); + unit_addorder(u, create_order(K_SELL, u->faction->locale, 0)); + update_long_order(u); + CuAssertPtrEquals(tc, 0, u->thisorder); + CuAssertPtrNotNull(tc, u->orders); + CuAssertPtrEquals(tc, 0, u->faction->msgs); + test_cleanup(); +} + +static void test_long_order_multi_long(CuTest *tc) { + // TODO: write more tests + unit *u; + test_cleanup(); + u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0)); + u->faction->locale = get_or_create_locale("de"); + unit_addorder(u, create_order(K_MOVE, u->faction->locale, 0)); + unit_addorder(u, create_order(K_DESTROY, u->faction->locale, 0)); + update_long_order(u); + CuAssertPtrNotNull(tc, u->thisorder); + CuAssertPtrNotNull(tc, u->orders); + CuAssertStrEquals(tc, "error52", test_get_messagetype(u->faction->msgs->begin->msg)); + test_cleanup(); +} + +static void test_long_order_multi_buy(CuTest *tc) { + // TODO: write more tests + unit *u; + test_cleanup(); + u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0)); + u->faction->locale = get_or_create_locale("de"); + unit_addorder(u, create_order(K_BUY, u->faction->locale, 0)); + unit_addorder(u, create_order(K_BUY, u->faction->locale, 0)); + update_long_order(u); + CuAssertPtrEquals(tc, 0, u->thisorder); + CuAssertPtrNotNull(tc, u->orders); + CuAssertStrEquals(tc, "error52", test_get_messagetype(u->faction->msgs->begin->msg)); + test_cleanup(); +} + +static void test_long_order_multi_sell(CuTest *tc) { + // TODO: write more tests + unit *u; + test_cleanup(); + u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0)); + u->faction->locale = get_or_create_locale("de"); + unit_addorder(u, create_order(K_SELL, u->faction->locale, 0)); + unit_addorder(u, create_order(K_BUY, u->faction->locale, 0)); + unit_addorder(u, create_order(K_SELL, u->faction->locale, 0)); + update_long_order(u); + CuAssertPtrEquals(tc, 0, u->thisorder); + CuAssertPtrNotNull(tc, u->orders); + CuAssertPtrEquals(tc, 0, u->faction->msgs); + test_cleanup(); +} + +static void test_long_order_buy_cast(CuTest *tc) { + // TODO: write more tests + unit *u; + test_cleanup(); + u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0)); + u->faction->locale = get_or_create_locale("de"); + unit_addorder(u, create_order(K_BUY, u->faction->locale, 0)); + unit_addorder(u, create_order(K_CAST, u->faction->locale, 0)); + update_long_order(u); + CuAssertPtrEquals(tc, 0, u->thisorder); + CuAssertPtrNotNull(tc, u->orders); + CuAssertStrEquals(tc, "error52", test_get_messagetype(u->faction->msgs->begin->msg)); + test_cleanup(); +} + +static void test_long_order_hungry(CuTest *tc) { + // TODO: write more tests + unit *u; + test_cleanup(); + set_param(&global.parameters, "hunger.long", "1"); + u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0)); + fset(u, UFL_HUNGER); + u->faction->locale = get_or_create_locale("de"); + unit_addorder(u, create_order(K_MOVE, u->faction->locale, 0)); + unit_addorder(u, create_order(K_DESTROY, u->faction->locale, 0)); + set_default_order(K_WORK); + update_long_order(u); + CuAssertIntEquals(tc, K_WORK, getkeyword(u->thisorder)); + CuAssertPtrNotNull(tc, u->orders); + CuAssertPtrEquals(tc, 0, u->faction->msgs); + set_default_order(NOKEYWORD); + test_cleanup(); +} + +static void test_ally_cmd_errors(CuTest *tc) { + unit *u; + int fid; + order *ord; + + test_cleanup(); + u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0)); + u->faction->locale = get_or_create_locale("de"); + fid = u->faction->no + 1; + CuAssertPtrEquals(tc, 0, findfaction(fid)); + + ord = create_order(K_ALLY, u->faction->locale, itoa36(fid)); + ally_cmd(u, ord); + CuAssertStrEquals(tc, "error66", test_get_messagetype(u->faction->msgs->begin->msg)); + free_order(ord); + + test_cleanup(); +} + +static void test_ally_cmd(CuTest *tc) { + unit *u; + faction * f; + order *ord; + struct locale *lang; + + test_cleanup(); + u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0)); + f = test_create_faction(0); + u->faction->locale = lang = get_or_create_locale("de"); + locale_setstring(lang, parameters[P_NOT], "NICHT"); + locale_setstring(lang, parameters[P_GUARD], "BEWACHE"); + init_parameters(lang); + + ord = create_order(K_ALLY, lang, "%s", itoa36(f->no)); + ally_cmd(u, ord); + CuAssertPtrEquals(tc, 0, u->faction->msgs); + CuAssertIntEquals(tc, HELP_ALL, alliedfaction(0, u->faction, f, HELP_ALL)); + free_order(ord); + + ord = create_order(K_ALLY, lang, "%s NICHT", itoa36(f->no)); + ally_cmd(u, ord); + CuAssertPtrEquals(tc, 0, u->faction->msgs); + CuAssertIntEquals(tc, 0, alliedfaction(0, u->faction, f, HELP_ALL)); + free_order(ord); + + ord = create_order(K_ALLY, lang, "%s BEWACHE", itoa36(f->no)); + ally_cmd(u, ord); + CuAssertPtrEquals(tc, 0, u->faction->msgs); + CuAssertIntEquals(tc, HELP_GUARD, alliedfaction(0, u->faction, f, HELP_ALL)); + free_order(ord); + + ord = create_order(K_ALLY, lang, "%s BEWACHE NICHT", itoa36(f->no)); + ally_cmd(u, ord); + CuAssertPtrEquals(tc, 0, u->faction->msgs); + CuAssertIntEquals(tc, 0, alliedfaction(0, u->faction, f, HELP_ALL)); + free_order(ord); + + test_cleanup(); +} + CuSuite *get_laws_suite(void) { CuSuite *suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_ally_cmd); + SUITE_ADD_TEST(suite, test_ally_cmd_errors); + SUITE_ADD_TEST(suite, test_long_order_normal); + SUITE_ADD_TEST(suite, test_long_order_none); + SUITE_ADD_TEST(suite, test_long_order_cast); + SUITE_ADD_TEST(suite, test_long_order_buy_sell); + SUITE_ADD_TEST(suite, test_long_order_multi_long); + SUITE_ADD_TEST(suite, test_long_order_multi_buy); + SUITE_ADD_TEST(suite, test_long_order_multi_sell); + SUITE_ADD_TEST(suite, test_long_order_buy_cast); + SUITE_ADD_TEST(suite, test_long_order_hungry); SUITE_ADD_TEST(suite, test_new_building_can_be_renamed); SUITE_ADD_TEST(suite, test_rename_building); SUITE_ADD_TEST(suite, test_rename_building_twice); @@ -777,6 +1012,7 @@ CuSuite *get_laws_suite(void) SUITE_ADD_TEST(suite, test_enter_building); SUITE_ADD_TEST(suite, test_enter_ship); SUITE_ADD_TEST(suite, test_display_cmd); + SUITE_ADD_TEST(suite, test_rule_force_leave); SUITE_ADD_TEST(suite, test_force_leave_buildings); SUITE_ADD_TEST(suite, test_force_leave_ships); SUITE_ADD_TEST(suite, test_force_leave_ships_on_ocean); diff --git a/src/magic.c b/src/magic.c index 72fe72a25..075880020 100644 --- a/src/magic.c +++ b/src/magic.c @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 1998-2014, Enno Rehling Katja Zedel #include #include +#include #include const char *magic_school[MAXMAGIETYP] = { @@ -117,12 +118,12 @@ static float MagicRegeneration(void) return value; } -float MagicPower(void) +double MagicPower(void) { - static float value = -1.0; + static double value = -1.0; if (value < 0) { const char *str = get_param(global.parameters, "magic.power"); - value = str ? (float)atof(str) : 1.0f; + value = str ? atof(str) : 1.0; } return value; } @@ -193,7 +194,7 @@ attrib_type at_icastle = { extern int dice(int count, int value); /* ------------------------------------------------------------- */ -/* aus dem alten System briggebliegene Funktionen, die bei der +/* aus dem alten System übriggebliegene Funktionen, die bei der * Umwandlung von alt nach neu gebraucht werden */ /* ------------------------------------------------------------- */ @@ -352,9 +353,9 @@ sc_mage *get_mage(const unit * u) /* ------------------------------------------------------------- */ /* Ausgabe der Spruchbeschreibungen * Anzeige des Spruchs nur, wenn die Stufe des besten Magiers vorher -* kleiner war (u->faction->seenspells). Ansonsten muss nur geprft +* kleiner war (u->faction->seenspells). Ansonsten muss nur geprüft * werden, ob dieser Magier den Spruch schon kennt, und andernfalls der -* Spruch zu seiner List-of-known-spells hinzugefgt werden. +* Spruch zu seiner List-of-known-spells hinzugefügt werden. */ static int read_seenspell(attrib * a, void *owner, struct storage *store) @@ -507,7 +508,7 @@ sc_mage *create_mage(unit * u, magic_t mtyp) } /* ------------------------------------------------------------- */ -/* Funktionen fr die Bearbeitung der List-of-known-spells */ +/* Funktionen für die Bearbeitung der List-of-known-spells */ int u_hasspell(const unit *u, const struct spell *sp) { @@ -535,7 +536,7 @@ int get_combatspelllevel(const unit * u, int nr) } /* ------------------------------------------------------------- */ -/* Kampfzauber ermitteln, setzen oder lschen */ +/* Kampfzauber ermitteln, setzen oder löschen */ const spell *get_combatspell(const unit * u, int nr) { @@ -560,7 +561,7 @@ void set_combatspell(unit * u, spell * sp, struct order *ord, int level) assert(mage || !"trying to set a combat spell for non-mage"); - /* knowsspell prft auf ist_magier, ist_spruch, kennt_spruch */ + /* knowsspell prüft auf ist_magier, ist_spruch, kennt_spruch */ if (!knowsspell(u->region, u, sp)) { /* Fehler 'Spell not found' */ cmistake(u, ord, 173, MSG_MAGIC); @@ -626,7 +627,7 @@ void unset_combatspell(unit * u, spell * sp) } /* ------------------------------------------------------------- */ -/* Gibt die aktuelle Anzahl der Magiepunkte der Einheit zurck */ +/* Gibt die aktuelle Anzahl der Magiepunkte der Einheit zurück */ int get_spellpoints(const unit * u) { sc_mage *m; @@ -652,7 +653,7 @@ void set_spellpoints(unit * u, int sp) } /* - * verndert die Anzahl der Magiepunkte der Einheit um +mp + * verändert die Anzahl der Magiepunkte der Einheit um +mp */ int change_spellpoints(unit * u, int mp) { @@ -671,7 +672,7 @@ int change_spellpoints(unit * u, int mp) return sp; } -/* bietet die Mglichkeit, die maximale Anzahl der Magiepunkte mit +/* bietet die Möglichkeit, die maximale Anzahl der Magiepunkte mit * Regionszaubern oder Attributen zu beinflussen */ static int get_spchange(const unit * u) @@ -687,13 +688,13 @@ static int get_spchange(const unit * u) /* ein Magier kann normalerweise maximal Stufe^2.1/1.2+1 Magiepunkte * haben. - * Manche Rassen haben einen zustzlichen Multiplikator - * Durch Talentverlust (zB Insekten im Berg) knnen negative Werte + * Manche Rassen haben einen zusätzlichen Multiplikator + * Durch Talentverlust (zB Insekten im Berg) können negative Werte * entstehen */ -/* Artefakt der Strke - * Ermglicht dem Magier mehr Magiepunkte zu 'speichern' +/* Artefakt der Stärke + * Ermöglicht dem Magier mehr Magiepunkte zu 'speichern' */ /** TODO: at_skillmod daraus machen */ static int use_item_aura(const region * r, const unit * u) @@ -741,8 +742,8 @@ int change_maxspellpoints(unit * u, int csp) } /* ------------------------------------------------------------- */ -/* Counter fr die bereits gezauberte Anzahl Sprche pro Runde. - * Um nur die Zahl der bereits gezauberten Sprche zu ermitteln mit +/* Counter für die bereits gezauberte Anzahl Sprüche pro Runde. + * Um nur die Zahl der bereits gezauberten Sprüche zu ermitteln mit * step = 0 aufrufen. */ int countspells(unit * u, int step) @@ -766,9 +767,9 @@ int countspells(unit * u, int step) } /* ------------------------------------------------------------- */ -/* Die fr den Spruch bentigte Aura pro Stufe. - * Die Grundkosten pro Stufe werden hier um 2^count erhht. Der - * Parameter count ist dabei die Anzahl der bereits gezauberten Sprche +/* Die für den Spruch benötigte Aura pro Stufe. + * Die Grundkosten pro Stufe werden hier um 2^count erhöht. Der + * Parameter count ist dabei die Anzahl der bereits gezauberten Sprüche */ int spellcost(unit * u, const spell * sp) { @@ -776,7 +777,7 @@ int spellcost(unit * u, const spell * sp) int count = countspells(u, 0); const resource_type *r_aura = get_resourcetype(R_AURA); - for (k = 0; sp->components[k].type; k++) { + for (k = 0; sp->components && sp->components[k].type; k++) { if (sp->components[k].type == r_aura) { aura = sp->components[k].amount; } @@ -786,18 +787,18 @@ int spellcost(unit * u, const spell * sp) } /* ------------------------------------------------------------- */ -/* SPC_LINEAR ist am hchstwertigen, dann mssen Komponenten fr die +/* SPC_LINEAR ist am höchstwertigen, dann müssen Komponenten für die * Stufe des Magiers vorhanden sein. - * SPC_LINEAR hat die gewnschte Stufe als multiplikator, + * SPC_LINEAR hat die gewünschte Stufe als multiplikator, * nur SPC_FIX muss nur einmal vorhanden sein, ist also am * niedrigstwertigen und sollte von den beiden anderen Typen - * berschrieben werden */ + * überschrieben werden */ static int spl_costtyp(const spell * sp) { int k; int costtyp = SPC_FIX; - for (k = 0; sp->components[k].type; k++) { + for (k = 0; sp->components && sp->components[k].type; k++) { if (costtyp == SPC_LINEAR) return SPC_LINEAR; @@ -805,7 +806,7 @@ static int spl_costtyp(const spell * sp) return SPC_LINEAR; } - /* wenn keine Fixkosten, Typ bernehmen */ + /* wenn keine Fixkosten, Typ übernehmen */ if (sp->components[k].cost != SPC_FIX) { costtyp = sp->components[k].cost; } @@ -814,10 +815,10 @@ static int spl_costtyp(const spell * sp) } /* ------------------------------------------------------------- */ -/* durch Komponenten und cast_level begrenzter maximal mglicher +/* durch Komponenten und cast_level begrenzter maximal möglicher * Level * Da die Funktion nicht alle Komponenten durchprobiert sondern beim - * ersten Fehler abbricht, muss die Fehlermeldung spter mit cancast() + * ersten Fehler abbricht, muss die Fehlermeldung später mit cancast() * generiert werden. * */ int eff_spelllevel(unit * u, const spell * sp, int cast_level, int range) @@ -826,13 +827,13 @@ int eff_spelllevel(unit * u, const spell * sp, int cast_level, int range) int k, maxlevel, needplevel; int costtyp = SPC_FIX; - for (k = 0; sp->components[k].type; k++) { + for (k = 0; sp->components && sp->components[k].type; k++) { if (cast_level == 0) return 0; if (sp->components[k].amount > 0) { - /* Die Kosten fr Aura sind auch von der Zahl der bereits - * gezauberten Sprche abhngig */ + /* Die Kosten für Aura sind auch von der Zahl der bereits + * gezauberten Sprüche abhängig */ if (sp->components[k].type == r_aura) { needplevel = spellcost(u, sp) * range; } @@ -844,18 +845,18 @@ int eff_spelllevel(unit * u, const spell * sp, int cast_level, int range) needplevel * cast_level) / needplevel; /* sind die Kosten fix, so muss die Komponente nur einmal vorhanden - * sein und der cast_level ndert sich nicht */ + * sein und der cast_level ändert sich nicht */ if (sp->components[k].cost == SPC_FIX) { if (maxlevel < 1) cast_level = 0; - /* ansonsten wird das Minimum aus maximal mglicher Stufe und der - * gewnschten gebildet */ + /* ansonsten wird das Minimum aus maximal möglicher Stufe und der + * gewünschten gebildet */ } else if (sp->components[k].cost == SPC_LEVEL) { costtyp = SPC_LEVEL; cast_level = _min(cast_level, maxlevel); - /* bei Typ Linear mssen die Kosten in Hhe der Stufe vorhanden - * sein, ansonsten schlgt der Spruch fehl */ + /* bei Typ Linear müssen die Kosten in Höhe der Stufe vorhanden + * sein, ansonsten schlägt der Spruch fehl */ } else if (sp->components[k].cost == SPC_LINEAR) { costtyp = SPC_LINEAR; @@ -882,7 +883,7 @@ int eff_spelllevel(unit * u, const spell * sp, int cast_level, int range) /* ------------------------------------------------------------- */ /* Die Spruchgrundkosten werden mit der Entfernung (Farcasting) * multipliziert, wobei die Aurakosten ein Sonderfall sind, da sie sich - * auch durch die Menge der bereits gezauberten Sprche erhht. + * auch durch die Menge der bereits gezauberten Sprüche erhöht. * Je nach Kostenart werden dann die Komponenten noch mit cast_level * multipliziert. */ @@ -893,7 +894,7 @@ void pay_spell(unit * u, const spell * sp, int cast_level, int range) int resuse; assert(cast_level > 0); - for (k = 0; sp->components[k].type; k++) { + for (k = 0; sp->components && sp->components[k].type; k++) { if (sp->components[k].type == r_aura) { resuse = spellcost(u, sp) * range; } @@ -913,12 +914,12 @@ void pay_spell(unit * u, const spell * sp, int cast_level, int range) /* ------------------------------------------------------------- */ /* Ein Magier kennt den Spruch und kann sich die Beschreibung anzeigen * lassen, wenn diese in seiner Spruchliste steht. Zaubern muss er ihn - * aber dann immer noch nicht knnen, vieleicht ist seine Stufe derzeit + * aber dann immer noch nicht können, vieleicht ist seine Stufe derzeit * nicht ausreichend oder die Komponenten fehlen. */ bool knowsspell(const region * r, const unit * u, const spell * sp) { - /* Ist berhaupt ein gltiger Spruch angegeben? */ + /* Ist überhaupt ein gültiger Spruch angegeben? */ if (!sp || sp->id == 0) { return false; } @@ -929,7 +930,7 @@ bool knowsspell(const region * r, const unit * u, const spell * sp) /* Um einen Spruch zu beherrschen, muss der Magier die Stufe des * Spruchs besitzen, nicht nur wissen, das es ihn gibt (also den Spruch * in seiner Spruchliste haben). - * Kosten fr einen Spruch knnen Magiepunkte, Silber, Kraeuter + * Kosten für einen Spruch können Magiepunkte, Silber, Kraeuter * und sonstige Gegenstaende sein. */ @@ -948,18 +949,18 @@ cancast(unit * u, const spell * sp, int level, int range, struct order * ord) } /* reicht die Stufe aus? */ if (eff_skill(u, SK_MAGIC, u->region) < level) { - /* die Einheit ist nicht erfahren genug fr diesen Zauber */ + /* die Einheit ist nicht erfahren genug für diesen Zauber */ cmistake(u, ord, 169, MSG_MAGIC); return false; } - for (k = 0; sp->components[k].type; ++k) { + for (k = 0; sp->components && sp->components[k].type; ++k) { if (sp->components[k].amount > 0) { const resource_type *rtype = sp->components[k].type; int itemhave; - /* Die Kosten fr Aura sind auch von der Zahl der bereits - * gezauberten Sprche abhngig */ + /* Die Kosten für Aura sind auch von der Zahl der bereits + * gezauberten Sprüche abhängig */ if (rtype == r_aura) { itemanz = spellcost(u, sp) * range; } @@ -967,7 +968,7 @@ cancast(unit * u, const spell * sp, int level, int range, struct order * ord) itemanz = sp->components[k].amount * range; } - /* sind die Kosten stufenabhngig, so muss itemanz noch mit dem + /* sind die Kosten stufenabhängig, so muss itemanz noch mit dem * level multipliziert werden */ switch (sp->components[k].cost) { case SPC_LEVEL: @@ -1004,15 +1005,15 @@ cancast(unit * u, const spell * sp, int level, int range, struct order * ord) * Spruchitems und Antimagiefeldern zusammen. Es koennen noch die * Stufe des Spruchs und Magiekosten mit einfliessen. * - * Die effektive Spruchstrke und ihre Auswirkungen werden in der + * Die effektive Spruchstärke und ihre Auswirkungen werden in der * Spruchfunktionsroutine ermittelt. */ -float +double spellpower(region * r, unit * u, const spell * sp, int cast_level, struct order *ord) { curse *c; - float force = (float)cast_level; + double force = cast_level; int elf_power; const struct resource_type *rtype; @@ -1041,7 +1042,7 @@ spellpower(region * r, unit * u, const spell * sp, int cast_level, struct order if (curse_active(c)) { unit *mage = c->magician; force -= curse_geteffect(c); - curse_changevigour(&r->attribs, c, (float)-cast_level); + curse_changevigour(&r->attribs, c, -cast_level); cmistake(u, ord, 185, MSG_MAGIC); if (mage != NULL && mage->faction != NULL) { if (force > 0) { @@ -1080,7 +1081,7 @@ spellpower(region * r, unit * u, const spell * sp, int cast_level, struct order } /* ------------------------------------------------------------- */ -/* farcasting() == 1 -> gleiche Region, da man mit Null nicht vernnfigt +/* farcasting() == 1 -> gleiche Region, da man mit Null nicht vernünfigt * rechnen kann */ static int farcasting(unit * magician, region * r) { @@ -1166,7 +1167,7 @@ double magic_resistance(unit * target) /* Bonus durch Artefakte */ /* TODO (noch gibs keine) */ - /* Bonus durch Gebude */ + /* Bonus durch Gebäude */ { struct building *b = inside_building(target); const struct building_type *btype = b ? b->type : NULL; @@ -1179,14 +1180,14 @@ double magic_resistance(unit * target) } /* ------------------------------------------------------------- */ -/* Prft, ob das Objekt dem Zauber widerstehen kann. - * Objekte knnen Regionen, Units, Gebude oder Schiffe sein. +/* Prüft, ob das Objekt dem Zauber widerstehen kann. + * Objekte können Regionen, Units, Gebäude oder Schiffe sein. * TYP_UNIT: - * Das hchste Talent des Ziels ist sein 'Magieresistenz-Talent', Magier - * bekommen einen Bonus. Grundchance ist 50%, fr jede Stufe - * Unterschied gibt es 5%, minimalchance ist 5% fr jeden (5-95%) + * Das höchste Talent des Ziels ist sein 'Magieresistenz-Talent', Magier + * bekommen einen Bonus. Grundchance ist 50%, für jede Stufe + * Unterschied gibt es 5%, minimalchance ist 5% für jeden (5-95%) * Scheitert der Spruch an der Magieresistenz, so gibt die Funktion - * true zurck + * true zurück */ bool @@ -1248,8 +1249,8 @@ target_resists_magic(unit * magician, void *obj, int objtyp, int t_bonus) probability = _min(0.98, probability); /* gibt true, wenn die Zufallszahl kleiner als die chance ist und - * false, wenn sie gleich oder grer ist, dh je grer die - * Magieresistenz (chance) desto eher gibt die Funktion true zurck */ + * false, wenn sie gleich oder größer ist, dh je größer die + * Magieresistenz (chance) desto eher gibt die Funktion true zurück */ return chance(probability); } @@ -1276,7 +1277,7 @@ bool fumble(region * r, unit * u, const spell * sp, int cast_grade) { /* X ergibt Zahl zwischen 1 und 0, je kleiner, desto besser der Magier. * 0,5*40-20=0, dh wenn der Magier doppelt so gut ist, wie der Spruch - * bentigt, gelingt er immer, ist er gleich gut, gelingt der Spruch mit + * benötigt, gelingt er immer, ist er gleich gut, gelingt der Spruch mit * 20% Warscheinlichkeit nicht * */ @@ -1306,8 +1307,8 @@ bool fumble(region * r, unit * u, const spell * sp, int cast_grade) fumble_chance += CHAOSPATZERCHANCE; } - /* wenn die Chance kleiner als 0 ist, knnen wir gleich false - * zurckgeben */ + /* wenn die Chance kleiner als 0 ist, können wir gleich false + * zurückgeben */ if (fumble_chance <= 0) { return false; } @@ -1317,7 +1318,7 @@ bool fumble(region * r, unit * u, const spell * sp, int cast_grade) } /* ------------------------------------------------------------- */ -/* Dummy-Zauberpatzer, Platzhalter fr speziel auf die Sprche +/* Dummy-Zauberpatzer, Platzhalter für speziel auf die Sprüche * zugeschnittene Patzer */ static void fumble_default(castorder * co) { @@ -1328,7 +1329,7 @@ static void fumble_default(castorder * co) return; } -/* Die normalen Spruchkosten mssen immer bezahlt werden, hier noch +/* Die normalen Spruchkosten müssen immer bezahlt werden, hier noch * alle weiteren Folgen eines Patzers */ @@ -1340,7 +1341,7 @@ static void do_fumble(castorder * co) const spell *sp = co->sp; int level = co->level; int duration; - float effect; + double effect; ADDMSG(&u->faction->msgs, msg_message("patzer", "unit region spell", u, r, sp)); @@ -1382,15 +1383,15 @@ static void do_fumble(castorder * co) case 2: /* temporary skill loss */ duration = _max(rng_int() % level / 2, 2); - effect = -(float)level / 2; - c = create_curse(u, &u->attribs, ct_find("skillmod"), (float)level, + effect = level / -2.0; + c = create_curse(u, &u->attribs, ct_find("skillmod"), level, duration, effect, 1); c->data.i = SK_MAGIC; ADDMSG(&u->faction->msgs, msg_message("patzer2", "unit region", u, r)); break; case 3: case 4: - /* Spruch schlgt fehl, alle Magiepunkte weg */ + /* Spruch schlägt fehl, alle Magiepunkte weg */ set_spellpoints(u, 0); ADDMSG(&u->faction->msgs, msg_message("patzer3", "unit region spell", u, r, sp)); @@ -1409,7 +1410,7 @@ static void do_fumble(castorder * co) case 8: case 9: default: - /* Spruch gelingt, alle nachfolgenden Sprche werden 2^4 so teuer */ + /* Spruch gelingt, alle nachfolgenden Sprüche werden 2^4 so teuer */ co->level = sp->cast(co); ADDMSG(&u->faction->msgs, msg_message("patzer5", "unit region spell", u, r, sp)); @@ -1422,7 +1423,7 @@ static void do_fumble(castorder * co) /* ------------------------------------------------------------- */ /* Ein Magier regeneriert pro Woche W(Stufe^1.5/2+1), mindestens 1 - * Zwerge nur die Hlfte + * Zwerge nur die Hälfte */ static double regeneration(unit * u) { @@ -1439,7 +1440,7 @@ static double regeneration(unit * u) /* Einfluss von Artefakten */ /* TODO (noch gibs keine) */ - /* Wrfeln */ + /* Würfeln */ aura = (rng_double() * d + rng_double() * d) / 2 + 1; aura *= MagicRegeneration(); @@ -1469,8 +1470,8 @@ void regenerate_aura(void) const struct building_type *btype = b ? b->type : NULL; reg_aura = regeneration(u); - /* Magierturm erhht die Regeneration um 75% */ - /* Steinkreis erhht die Regeneration um 50% */ + /* Magierturm erhöht die Regeneration um 75% */ + /* Steinkreis erhöht die Regeneration um 50% */ if (btype) reg_aura *= btype->auraregen; @@ -1609,14 +1610,14 @@ order * ord) /* ------------------------------------------------------------- */ /* Zuerst wird versucht alle noch nicht gefundenen Objekte zu finden - * oder zu prfen, ob das gefundene Objekt wirklich htte gefunden - * werden drfen (nicht alle Zauber wirken global). Dabei zhlen wir die + * oder zu prüfen, ob das gefundene Objekt wirklich hätte gefunden + * werden dürfen (nicht alle Zauber wirken global). Dabei zählen wir die * Misserfolge (failed). * Dann folgen die Tests der gefundenen Objekte auf Magieresistenz und - * Sichtbarkeit. Dabei zhlen wir die magieresistenten (resists) + * Sichtbarkeit. Dabei zählen wir die magieresistenten (resists) * Objekte. Alle anderen werten wir als Erfolge (success) */ -/* gibt bei Misserfolg 0 zurck, bei Magieresistenz zumindeste eines +/* gibt bei Misserfolg 0 zurück, bei Magieresistenz zumindeste eines * Objektes 1 und bei Erfolg auf ganzer Linie 2 */ static void verify_targets(castorder * co, int *invalid, int *resist, int *success) @@ -1634,8 +1635,8 @@ verify_targets(castorder * co, int *invalid, int *resist, int *success) if (sa && sa->length) { /* zuerst versuchen wir vorher nicht gefundene Objekte zu finden. * Wurde ein Objekt durch globalsuche gefunden, obwohl der Zauber - * gar nicht global htte suchen drften, setzen wir das Objekt - * zurck. */ + * gar nicht global hätte suchen dürften, setzen wir das Objekt + * zurück. */ for (i = 0; i < sa->length; i++) { spllprm *spobj = sa->param[i]; @@ -1719,7 +1720,7 @@ verify_targets(castorder * co, int *invalid, int *resist, int *success) case SPP_REGION: /* haben wir ein Regionsobjekt, dann wird auch dieses und - nicht target_r berprft. */ + nicht target_r überprüft. */ tr = spobj->data.r; if ((sp->sptyp & TESTRESISTANCE) @@ -1745,7 +1746,7 @@ verify_targets(castorder * co, int *invalid, int *resist, int *success) else { /* der Zauber hat keine expliziten Parameter/Ziele, es kann sich * aber um einen Regionszauber handeln. Wenn notwendig hier die - * Magieresistenz der Region prfen. */ + * Magieresistenz der Region prüfen. */ if ((sp->sptyp & REGIONSPELL)) { /* Zielobjekt Region anlegen */ spllprm *spobj = (spllprm *)malloc(sizeof(spllprm)); @@ -1782,16 +1783,17 @@ verify_targets(castorder * co, int *invalid, int *resist, int *success) } /* ------------------------------------------------------------- */ -/* Hilfsstrukturen fr ZAUBERE */ +/* Hilfsstrukturen für ZAUBERE */ /* ------------------------------------------------------------- */ static void free_spellparameter(spellparameter * pa) { int i; - /* Elemente free'en */ - for (i = 0; i < pa->length; i++) { + assert(pa->param); + for (i = 0; i < pa->length; i++) { + assert(pa->param[i]); switch (pa->param[i]->typ) { case SPP_STRING: free(pa->param[i]->data.s); @@ -1801,10 +1803,7 @@ static void free_spellparameter(spellparameter * pa) } free(pa->param[i]); } - - if (pa->param) - free(pa->param); - /* struct free'en */ + free(pa->param); free(pa); } @@ -1966,7 +1965,7 @@ static spellparameter *add_spellparameter(region * target_r, unit * u, break; case '+': /* das vorhergehende Element kommt ein oder mehrmals vor, wir - * springen zum key zurck */ + * springen zum key zurück */ j = 0; --c; break; @@ -2067,7 +2066,7 @@ struct region * co_get_region(const struct castorder * co) { } castorder *create_castorder(castorder * co, unit *caster, unit * familiar, const spell * sp, region * r, - int lev, float force, int range, struct order * ord, spellparameter * p) + int lev, double force, int range, struct order * ord, spellparameter * p) { if (!co) co = (castorder*)calloc(1, sizeof(castorder)); @@ -2090,7 +2089,7 @@ void free_castorder(struct castorder *co) if (co->order) free_order(co->order); } -/* Hnge c-order co an die letze c-order von cll an */ +/* Hänge c-order co an die letze c-order von cll an */ void add_castorder(spellrank * cll, castorder * co) { if (cll->begin == NULL) { @@ -2521,13 +2520,13 @@ static castorder *cast_cmd(unit * u, order * ord) init_order(ord); s = gettoken(token, sizeof(token)); param = findparam(s, u->faction->locale); - /* fr Syntax ' STUFE x REGION y z ' */ + /* für Syntax ' STUFE x REGION y z ' */ if (param == P_LEVEL) { int p = getint(); level = _min(p, level); if (level < 1) { /* Fehler "Das macht wenig Sinn" */ - cmistake(u, ord, 10, MSG_MAGIC); + syntax_error(u, ord); return 0; } s = gettoken(token, sizeof(token)); @@ -2550,19 +2549,19 @@ static castorder *cast_cmd(unit * u, order * ord) s = gettoken(token, sizeof(token)); param = findparam(s, u->faction->locale); } - /* fr Syntax ' REGION x y STUFE z ' - * hier nach REGION nochmal auf STUFE prfen */ + /* für Syntax ' REGION x y STUFE z ' + * hier nach REGION nochmal auf STUFE prüfen */ if (param == P_LEVEL) { int p = getint(); level = _min(p, level); if (level < 1) { /* Fehler "Das macht wenig Sinn" */ - cmistake(u, ord, 10, MSG_MAGIC); + syntax_error(u, ord); return 0; } s = gettoken(token, sizeof(token)); } - if (!s || !s[0] || strlen(s) == 0) { + if (!s || !s[0]) { /* Fehler "Es wurde kein Zauber angegeben" */ cmistake(u, ord, 172, MSG_MAGIC); return 0; @@ -2570,10 +2569,10 @@ static castorder *cast_cmd(unit * u, order * ord) sp = unit_getspell(u, s, u->faction->locale); - /* Vertraute knnen auch Zauber sprechen, die sie selbst nicht - * knnen. unit_getspell findet aber nur jene Sprche, die + /* Vertraute können auch Zauber sprechen, die sie selbst nicht + * können. unit_getspell findet aber nur jene Sprüche, die * die Einheit beherrscht. */ - if (!sp && is_familiar(u)) { + if (!sp && is_familiar(u)) { caster = get_familiar_mage(u); if (caster) { familiar = u; @@ -2594,7 +2593,7 @@ static castorder *cast_cmd(unit * u, order * ord) /* um testen auf spruchnamen zu unterbinden sollte vor allen * fehlermeldungen die anzeigen das der magier diesen Spruch * nur in diese Situation nicht anwenden kann, noch eine - * einfache Sicherheitsprfung kommen */ + * einfache Sicherheitsprüfung kommen */ if (!knowsspell(r, u, sp)) { /* vorsicht! u kann der familiar sein */ if (!familiar) { @@ -2607,9 +2606,9 @@ static castorder *cast_cmd(unit * u, order * ord) cmistake(u, ord, 174, MSG_MAGIC); return 0; } - /* Auf dem Ozean Zaubern als quasi-langer Befehl knnen + /* Auf dem Ozean Zaubern als quasi-langer Befehl können * normalerweise nur Meermenschen, ausgenommen explizit als - * OCEANCASTABLE deklarierte Sprche */ + * OCEANCASTABLE deklarierte Sprüche */ if (fval(r->terrain, SEA_REGION)) { if (u_race(u) != get_race(RC_AQUARIAN) && !fval(u_race(u), RCF_SWIM) @@ -2632,7 +2631,7 @@ static castorder *cast_cmd(unit * u, order * ord) } } } - /* Farcasting bei nicht farcastbaren Sprchen abfangen */ + /* Farcasting bei nicht farcastbaren Sprüchen abfangen */ range = farcasting(u, target_r); if (range > 1) { if (!(sp->sptyp & FARCASTING)) { @@ -2647,7 +2646,7 @@ static castorder *cast_cmd(unit * u, order * ord) return 0; } } - /* Stufenangabe bei nicht Stufenvariierbaren Sprchen abfangen */ + /* Stufenangabe bei nicht Stufenvariierbaren Sprüchen abfangen */ if (!(sp->sptyp & SPELLLEVEL)) { int ilevel = eff_skill(u, SK_MAGIC, u->region); if (ilevel != level) { @@ -2680,9 +2679,9 @@ static castorder *cast_cmd(unit * u, order * ord) "mage", caster)); return 0; } - /* mage auf magier setzen, level anpassen, range fr Erhhung + /* mage auf magier setzen, level anpassen, range für Erhöhung * der Spruchkosten nutzen, langen Befehl des Magiers - * lschen, zaubern kann er noch */ + * löschen, zaubern kann er noch */ range *= 2; set_order(&caster->thisorder, NULL); level = _min(level, eff_skill(caster, SK_MAGIC, caster->region) / 2); @@ -2697,8 +2696,16 @@ static castorder *cast_cmd(unit * u, order * ord) if (!s || *s == 0) break; if (p + 1 >= size) { - size *= 2; - params = (char**)realloc(params, sizeof(char *) * size); + char ** tmp; + tmp = (char**)realloc(params, sizeof(char *) * size * 2); + if (tmp) { + size *= 2; + params = tmp; + } + else { + log_error("error allocationg %d bytes: %s", size * 2, strerror(errno)); + break; + } } params[p++] = _strdup(s); } @@ -2721,19 +2728,19 @@ static castorder *cast_cmd(unit * u, order * ord) /* ------------------------------------------------------------- */ /* Damit man keine Rituale in fremden Gebiet machen kann, diese vor * Bewegung zaubern. Magier sind also in einem fremden Gebiet eine Runde - * lang verletzlich, da sie es betreten, und angegriffen werden knnen, - * bevor sie ein Ritual machen knnen. + * lang verletzlich, da sie es betreten, und angegriffen werden können, + * bevor sie ein Ritual machen können. * * Syntax: ZAUBER [REGION X Y] [STUFE ] "Spruchname" [Einheit-1 * Einheit-2 ..] * - * Nach Prioritt geordnet die Zauber global auswerten. + * Nach Priorität geordnet die Zauber global auswerten. * - * Die Kosten fr Farcasting multiplizieren sich mit der Entfernung, + * Die Kosten für Farcasting multiplizieren sich mit der Entfernung, * cast_level gibt die virtuelle Stufe an, die den durch das Farcasten * entstandenen Spruchkosten entspricht. Sind die Spruchkosten nicht - * levelabhngig, so sind die Kosten nur von der Entfernung bestimmt, - * die Strke/Level durch den realen Skill des Magiers + * levelabhängig, so sind die Kosten nur von der Entfernung bestimmt, + * die Stärke/Level durch den realen Skill des Magiers */ void magic(void) @@ -2761,26 +2768,24 @@ void magic(void) continue; } - if (u->thisorder != NULL) { - for (ord = u->orders; ord; ord = ord->next) { - if (getkeyword(ord) == K_CAST) { - castorder *co = cast_cmd(u, ord); - fset(u, UFL_LONGACTION | UFL_NOTMOVING); - if (co) { - const spell *sp = co->sp; - add_castorder(&spellranks[sp->rank], co); - } + for (ord = u->orders; ord; ord = ord->next) { + if (getkeyword(ord) == K_CAST) { + castorder *co = cast_cmd(u, ord); + fset(u, UFL_LONGACTION | UFL_NOTMOVING); + if (co) { + const spell *sp = co->sp; + add_castorder(&spellranks[sp->rank], co); } } } } } - /* Da sich die Aura und Komponenten in der Zwischenzeit verndert - * haben knnen und sich durch vorherige Sprche das Zaubern - * erschwert haben kann, muss beim zaubern erneut geprft werden, ob der - * Spruch berhaupt gezaubert werden kann. - * (level) die effektive Strke des Spruchs (= Stufe, auf der der + /* Da sich die Aura und Komponenten in der Zwischenzeit verändert + * haben können und sich durch vorherige Sprüche das Zaubern + * erschwert haben kann, muss beim zaubern erneut geprüft werden, ob der + * Spruch überhaupt gezaubert werden kann. + * (level) die effektive Stärke des Spruchs (= Stufe, auf der der * Spruch gezaubert wird) */ for (rank = 0; rank < MAX_SPELLRANK; rank++) { @@ -2802,30 +2807,30 @@ void magic(void) } if (cast_level > co->level) { - /* Sprche mit Fixkosten werden immer auf Stufe des Spruchs - * gezaubert, co->level ist aber defaultmig Stufe des Magiers */ + /* Sprüche mit Fixkosten werden immer auf Stufe des Spruchs + * gezaubert, co->level ist aber defaultmäßig Stufe des Magiers */ if (spl_costtyp(sp) != SPC_FIX) { ADDMSG(&u->faction->msgs, msg_message("missing_components", "unit spell level", u, sp, cast_level)); } } - /* Prfen, ob die realen Kosten fr die gewnschten Stufe bezahlt - * werden knnen */ + /* Prüfen, ob die realen Kosten für die gewünschten Stufe bezahlt + * werden können */ if (!cancast(u, sp, co->level, co->distance, ord)) { /* die Fehlermeldung wird in cancast generiert */ continue; } co->force = spellpower(target_r, u, sp, co->level, ord); - /* die Strke kann durch Antimagie auf 0 sinken */ + /* die Stärke kann durch Antimagie auf 0 sinken */ if (co->force <= 0) { co->force = 0; ADDMSG(&u->faction->msgs, msg_message("missing_force", "unit spell level", u, sp, co->level)); } - /* Ziele auf Existenz prfen und Magieresistenz feststellen. Wurde + /* Ziele auf Existenz prüfen und Magieresistenz feststellen. Wurde * kein Ziel gefunden, so ist verify_targets=0. Scheitert der * Spruch an der Magieresistenz, so ist verify_targets = 1, bei * Erfolg auf ganzer Linie ist verify_targets= 2 @@ -2833,8 +2838,8 @@ void magic(void) verify_targets(co, &invalid, &resist, &success); if (success + resist == 0) { /* kein Ziel gefunden, Fehlermeldungen sind in verify_targets */ - /* keine kosten fr den zauber */ - continue; /* uere Schleife, nchster Zauberer */ + /* keine kosten für den zauber */ + continue; /* äußere Schleife, nächster Zauberer */ } else if (co->force > 0 && resist > 0) { /* einige oder alle Ziele waren magieresistent */ @@ -2847,8 +2852,8 @@ void magic(void) } } - /* Auch fr Patzer gibt es Erfahrung, mssen die Spruchkosten - * bezahlt werden und die nachfolgenden Sprche werden teurer */ + /* Auch für Patzer gibt es Erfahrung, müssen die Spruchkosten + * bezahlt werden und die nachfolgenden Sprüche werden teurer */ if (co->force > 0) { if (fumble(target_r, u, sp, co->level)) { /* zuerst bezahlen, dann evt in do_fumble alle Aura verlieren */ @@ -2857,12 +2862,12 @@ void magic(void) else { co->level = sp->cast(co); if (co->level <= 0) { - /* Kosten nur fr real bentige Stufe berechnen */ + /* Kosten nur für real benötige Stufe berechnen */ continue; } } } - /* erst bezahlen, dann Kostenzhler erhhen */ + /* erst bezahlen, dann Kostenzähler erhöhen */ if (co->level > 0) { pay_spell(u, sp, co->level, co->distance); } @@ -2964,7 +2969,7 @@ spellbook * get_spellbook(const char * name) { char buffer[64]; spellbook * result; - const void * match; + void * match; if (cb_find_prefix(&cb_spellbooks, name, strlen(name), &match, 1, 0)) { cb_get_kv(match, &result, sizeof(result)); diff --git a/src/magic.h b/src/magic.h index 1494b0170..39d5877e0 100644 --- a/src/magic.h +++ b/src/magic.h @@ -58,7 +58,7 @@ extern "C" { sppobj_t typ; int flag; union { - struct region *r; + struct region *r; //TODO: V117 http://www.viva64.com/en/V117 Memsize type is used in the union. struct unit *u; struct building *b; struct ship *sh; @@ -131,7 +131,7 @@ extern "C" { den Vertrauten gezaubert wird */ const struct spell *sp; /* Spruch */ int level; /* gewnschte Stufe oder Stufe des Magiers */ - float force; /* Strke des Zaubers */ + double force; /* Strke des Zaubers */ struct region *_rtarget; /* Zielregion des Spruchs */ int distance; /* Entfernung zur Zielregion */ struct order *order; /* Befehl */ @@ -277,7 +277,7 @@ extern "C" { /* verndert die maximalen Magiepunkte einer Einheit */ /* Zaubern */ - extern float spellpower(struct region *r, struct unit *u, const struct spell * sp, + extern double spellpower(struct region *r, struct unit *u, const struct spell * sp, int cast_level, struct order *ord); /* ermittelt die Strke eines Spruchs */ bool fumble(struct region *r, struct unit *u, const struct spell * sp, @@ -291,7 +291,7 @@ extern "C" { struct castorder *create_castorder(struct castorder * co, struct unit *caster, struct unit * familiar, const struct spell * sp, struct region * r, - int lev, float force, int range, struct order * ord, struct spellparameter * p); + int lev, double force, int range, struct order * ord, struct spellparameter * p); void free_castorder(struct castorder *co); /* Zwischenspreicher fr Zauberbefehle, notwendig fr Prioritten */ void add_castorder(struct spellrank *cll, struct castorder *co); @@ -360,7 +360,7 @@ extern "C" { extern void write_spells(struct quicklist *slist, struct storage *store); extern void read_spells(struct quicklist **slistp, magic_t mtype, struct storage *store); - extern float MagicPower(void); + extern double MagicPower(void); extern struct spellbook * get_spellbook(const char * name); extern void free_spellbooks(void); diff --git a/src/magic.test.c b/src/magic.test.c index 9a01d5d4e..600f724ca 100644 --- a/src/magic.test.c +++ b/src/magic.test.c @@ -3,6 +3,7 @@ #include "magic.h" #include +#include #include #include #include @@ -382,9 +383,45 @@ void test_hasspell(CuTest * tc) test_cleanup(); } +static quicklist * casts; + +static int cast_fireball(struct castorder * co) { + ql_push(&casts, co); + return 0; +} + +void test_multi_cast(CuTest *tc) { + unit *u; + spell *sp; + struct locale * lang; + + test_cleanup(); + sp = create_spell("fireball", 0); + sp->cast = cast_fireball; + CuAssertPtrEquals(tc, sp, find_spell("fireball")); + + u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0)); + u->faction->locale = lang = get_or_create_locale("de"); + locale_setstring(lang, mkname("spell", sp->sname), "Feuerball"); + CuAssertStrEquals(tc, "Feuerball", spell_name(sp, lang)); + set_level(u, SK_MAGIC, 10); + unit_add_spell(u, 0, sp, 1); + CuAssertPtrEquals(tc, sp, unit_getspell(u, "Feuerball", lang)); + + unit_addorder(u, create_order(K_CAST, u->faction->locale, "Feuerball")); + unit_addorder(u, create_order(K_CAST, u->faction->locale, "Feuerball")); + CuAssertPtrEquals(tc, casts, 0); + magic(); + CuAssertPtrNotNull(tc, casts); + CuAssertIntEquals(tc, 2, ql_length(casts)); + ql_free(casts); + test_cleanup(); +} + CuSuite *get_magic_suite(void) { CuSuite *suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_multi_cast); SUITE_ADD_TEST(suite, test_updatespells); SUITE_ADD_TEST(suite, test_spellbooks); SUITE_ADD_TEST(suite, test_pay_spell); diff --git a/src/main.c b/src/main.c index 547e15548..a1ebc6f06 100644 --- a/src/main.c +++ b/src/main.c @@ -132,32 +132,33 @@ static int parse_args(int argc, char **argv, int *exitcode) int i; for (i = 1; i != argc; ++i) { - if (argv[i][0] != '-') { - luafile = argv[i]; + char *argi = argv[i]; + if (argi[0] != '-') { + luafile = argi; } - else if (argv[i][1] == '-') { /* long format */ - if (strcmp(argv[i] + 2, "version") == 0) { + 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: %d.%d.%d\n\n", game_name(), VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD); #ifdef USE_CURSES } - else if (strcmp(argv[i] + 2, "color") == 0) { + else if (strcmp(argi + 2, "color") == 0) { /* force the editor to have colors */ force_color = 1; #endif } - else if (strcmp(argv[i] + 2, "help") == 0) { + else if (strcmp(argi + 2, "help") == 0) { return usage(argv[0], NULL); } else { - return usage(argv[0], argv[i]); + return usage(argv[0], argi); } } else { const char *arg; - switch (argv[i][1]) { + switch (argi[1]) { case 'r': i = get_arg(argc, argv, 2, i, &arg, 0); set_param(&global.parameters, "config.rules", arg); @@ -184,7 +185,7 @@ static int parse_args(int argc, char **argv, int *exitcode) return 1; default: *exitcode = -1; - usage(argv[0], argv[i]); + usage(argv[0], argi); return 1; } } @@ -282,7 +283,6 @@ int main(int argc, char **argv) int err = 0; lua_State *L; setup_signal_handler(); - /* parse args once to read config file location */ if (parse_args(argc, argv, &err) != 0) { return err; diff --git a/src/modules/arena.c b/src/modules/arena.c index fa08d74ac..fea4743de 100644 --- a/src/modules/arena.c +++ b/src/modules/arena.c @@ -49,7 +49,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include #include -#include +#include #include #include #include diff --git a/src/modules/autoseed.c b/src/modules/autoseed.c index 44b93943c..dd73943f2 100644 --- a/src/modules/autoseed.c +++ b/src/modules/autoseed.c @@ -181,7 +181,7 @@ newfaction *read_newfactions(const char *filename) password[0] = '\0'; if (sscanf(buf, "%54s %20s %8s %d %d %16s %d", email, race, lang, &bonus, - &subscription, password, &alliance) < 6) + &subscription, password, &alliance) < 3) break; if (email[0] == '\0') break; @@ -904,10 +904,9 @@ static void smooth_island(region_list * island) } } -static void starting_region(region * r, region * rn[]) +static void starting_region(newfaction ** players, region * r, region * rn[]) { int n; - oceans_around(r, rn); freset(r, RF_MARK); for (n = 0; n != MAXDIRECTIONS; ++n) { @@ -915,11 +914,19 @@ static void starting_region(region * r, region * rn[]) } terraform_region(r, newterrain(T_PLAIN)); prepare_starting_region(r); - addplayer(r, addfaction("enno@eressea.de", itoa36(rng_int()), races, default_locale, 0)); + if (players && *players) { + newfaction *nf = *players; + const struct race *rc = nf->race ? nf->race : races; + const struct locale *lang = nf->lang ? nf->lang : default_locale; + const char * passwd = nf->password ? nf->password : itoa36(rng_int()); + addplayer(r, addfaction(nf->email, passwd, rc, lang, 0)); + *players = nf->next; + free_newfaction(nf); + } } /* E3A island generation */ -int build_island_e3(int x, int y, int numfactions, int minsize) +int build_island_e3(newfaction ** players, int x, int y, int numfactions, int minsize) { #define MIN_QUALITY 1000 int nfactions = 0; @@ -961,8 +968,8 @@ int build_island_e3(int x, int y, int numfactions, int minsize) get_neighbours(r, rn); q = region_quality(r, rn); - if (q >= MIN_QUALITY && nfactions < numfactions) { - starting_region(r, rn); + if (q >= MIN_QUALITY && nfactions < numfactions && *players) { + starting_region(players, r, rn); minq = _min(minq, q); maxq = _max(maxq, q); ++nfactions; @@ -976,8 +983,8 @@ int build_island_e3(int x, int y, int numfactions, int minsize) region *rn[MAXDIRECTIONS]; get_neighbours(r, rn); q = region_quality(r, rn); - if (q >= MIN_QUALITY * 4 / 3 && nfactions < numfactions) { - starting_region(r, rn); + if (q >= MIN_QUALITY * 4 / 3 && nfactions < numfactions && *players) { + starting_region(players, r, rn); minq = _min(minq, q); maxq = _max(maxq, q); ++nfactions; diff --git a/src/modules/autoseed.h b/src/modules/autoseed.h index 9844d017c..3cfe6225c 100644 --- a/src/modules/autoseed.h +++ b/src/modules/autoseed.h @@ -40,7 +40,7 @@ extern "C" { *terrains[], int distribution[], int size); extern int seed_adamantium(struct region *r, int base); - extern int build_island_e3(int x, int y, int numfactions, int minsize); + extern int build_island_e3(newfaction **players, int x, int y, int numfactions, int minsize); #ifdef __cplusplus } diff --git a/src/modules/museum.c b/src/modules/museum.c index 27722f0f3..4914e11bd 100644 --- a/src/modules/museum.c +++ b/src/modules/museum.c @@ -43,7 +43,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include #include -#include +#include #include #include diff --git a/src/modules/score.c b/src/modules/score.c index 644a79f49..26788199c 100644 --- a/src/modules/score.c +++ b/src/modules/score.c @@ -24,6 +24,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. /* kernel includes */ #include #include +#include #include #include #include @@ -161,8 +162,8 @@ void score(void) if (f->num_total != 0) { fprintf(scoreFP, "%8d (%8d/%4.2f%%/%5.2f) %30.30s (%3.3s) %5s (%3d)\n", f->score, f->score - average_score_of_age(f->age, f->age / 24 + 1), - ((float)f->score / (float)allscores) * 100.0, - (float)f->score / f->num_total, + ((double)f->score / allscores) * 100, + (double)f->score / f->num_total, f->name, LOC(default_locale, rc_name_s(f->race, NAME_SINGULAR)), factionid(f), f->age); } @@ -214,4 +215,20 @@ void score(void) } } +int default_score(const item_type *itype) { + int result = 0; + if (itype->construction) { + requirement *req = itype->construction->materials; + while (req->number) { + int score = req->rtype->itype ? req->rtype->itype->score : 10; + result += score * req->number * 2; + ++req; + } + } + else { + result = 10; + } + return result; +} + #endif diff --git a/src/modules/score.h b/src/modules/score.h index 0cbe6b749..7ffdf64e5 100644 --- a/src/modules/score.h +++ b/src/modules/score.h @@ -26,8 +26,11 @@ extern "C" { #error "must define SCORE_MODULE to use this module" #endif - extern void score(void); - extern int average_score_of_age(int age, int a); + struct item_type; + + void score(void); + int average_score_of_age(int age, int a); + int default_score(const struct item_type *itype); #ifdef __cplusplus } diff --git a/src/monster.h b/src/monster.h index fc3ca94a2..476bcb73e 100644 --- a/src/monster.h +++ b/src/monster.h @@ -31,8 +31,7 @@ extern "C" { void make_zombie(struct unit * u); #define MONSTER_ID 666 -#define is_monsters(f) (f && fval(f, FFL_NPC) && f==get_monsters()) - +#define is_monsters(f) (fval(f, FFL_NPC) && f==get_monsters()) #ifdef __cplusplus } diff --git a/src/monsters.c b/src/monsters.c index 85e043eed..d81ba7f81 100644 --- a/src/monsters.c +++ b/src/monsters.c @@ -74,6 +74,16 @@ #define DRAGON_RANGE 20 /* Max. Distanz zum nchsten Drachenziel */ #define MAXILLUSION_TEXTS 3 +static void give_peasants(unit *u, const item_type *itype, int reduce) { + char buf[64]; + slprintf(buf, sizeof(buf), "%s 0 %d %s", LOC(u->faction->locale, keyword(K_GIVE)), reduce, LOC(u->faction->locale, itype->rtype->_name)); + unit_addorder(u, parse_order(buf, u->faction->locale)); +} + +static float monster_attack_chance(void) { + return get_param_flt(global.parameters, "rules.monsters.attack_chance", 0.4f); +} + static void reduce_weight(unit * u) { int capacity, weight = 0; @@ -89,9 +99,11 @@ static void reduce_weight(unit * u) while (*itmp != NULL) { item *itm = *itmp; const item_type *itype = itm->type; - weight += itm->number * itype->weight; if (itype->flags & ITF_VEHICLE) { - give_item(itm->number, itm->type, u, NULL, NULL); + give_peasants(u, itm->type, itm->number); + } + else { + weight += itm->number * itype->weight; } if (*itmp == itm) itmp = &itm->next; @@ -109,7 +121,7 @@ static void reduce_weight(unit * u) && itype->rtype->atype == 0) { if (itype->capacity < itype->weight) { int reduce = _min(itm->number, -((capacity - weight) / itype->weight)); - give_item(reduce, itm->type, u, NULL, NULL); + give_peasants(u, itm->type, reduce); weight -= reduce * itype->weight; } } @@ -124,7 +136,7 @@ static void reduce_weight(unit * u) weight += itm->number * itype->weight; if (itype->capacity < itype->weight) { int reduce = _min(itm->number, -((capacity - weight) / itype->weight)); - give_item(reduce, itm->type, u, NULL, NULL); + give_peasants(u, itm->type, reduce); weight -= reduce * itype->weight; } if (*itmp == itm) @@ -132,10 +144,6 @@ static void reduce_weight(unit * u) } } -static float monster_attack_chance(void) { - return get_param_flt(global.parameters, "rules.monsters.attack_chance", 0.4f); -} - static order *monster_attack(unit * u, const unit * target) { if (u->region != target->region) @@ -665,8 +673,6 @@ static order *plan_dragon(unit * u) bool move = false; order *long_order = NULL; - reduce_weight(u); - if (ta == NULL) { move |= (r->land == 0 || r->land->peasants == 0); /* when no peasants, move */ move |= (r->land == 0 || r->land->money == 0); /* when no money, move */ @@ -717,6 +723,9 @@ static order *plan_dragon(unit * u) default: break; } + if (long_order) { + reduce_weight(u); + } if (rng_int() % 100 < 15) { const struct locale *lang = u->faction->locale; /* do a growl */ diff --git a/src/move.c b/src/move.c index b935789be..a9ed36b3e 100644 --- a/src/move.c +++ b/src/move.c @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 1998-2014, Enno Rehling Katja Zedel items, &animals, &acap, &vehicles, &vcap); - /* Man trgt sein eigenes Gewicht plus seine Kapazitt! Die Menschen - ** tragen nichts (siehe walkingcapacity). Ein Wagen zhlt nur, wenn er + /* Man trägt sein eigenes Gewicht plus seine Kapazität! Die Menschen + ** tragen nichts (siehe walkingcapacity). Ein Wagen zählt nur, wenn er ** von zwei Pferden gezogen wird */ animals = _min(animals, effskill(u, SK_RIDING) * u->number * 2); if (fval(u_race(u), RCF_HORSE)) animals += u->number; - /* maximal diese Pferde knnen zum Ziehen benutzt werden */ + /* maximal diese Pferde können zum Ziehen benutzt werden */ vehicles = _min(animals / HORSESNEEDED, vehicles); return vehicles * vcap + animals * acap; @@ -282,7 +282,7 @@ int walkingcapacity(const struct unit *u) people = u->number; } - /* maximal diese Pferde knnen zum Ziehen benutzt werden */ + /* maximal diese Pferde können zum Ziehen benutzt werden */ wagen_mit_pferden = _min(vehicles, pferde_fuer_wagen / HORSESNEEDED); n = wagen_mit_pferden * vcap; @@ -295,7 +295,7 @@ int walkingcapacity(const struct unit *u) /* Genug Trolle, um die Restwagen zu ziehen? */ wagen_mit_trollen = _min(u->number / 4, wagen_ohne_pferde); - /* Wagenkapazitt hinzuzhlen */ + /* Wagenkapazität hinzuzählen */ n += wagen_mit_trollen * vcap; wagen_ohne_pferde -= wagen_mit_trollen; } @@ -314,8 +314,11 @@ int walkingcapacity(const struct unit *u) } } if (rbelt) { - int tmp = i_get(u->items, rbelt->itype); - n += _min(people, tmp) * (STRENGTHMULTIPLIER - 1) * personcapacity(u); + int belts = i_get(u->items, rbelt->itype); + if (belts) { + int multi = get_param_int(global.parameters, "rules.trollbelt.multiplier", STRENGTHMULTIPLIER); + n += _min(people, belts) * (multi - 1) * u_race(u)->capacity; + } } return n; @@ -354,16 +357,16 @@ static int canwalk(unit * u) if (walkingcapacity(u) - eff_weight(u) >= 0) return E_CANWALK_OK; - /* Stimmt das Gewicht, impliziert dies hier, da alle Wagen ohne + /* Stimmt das Gewicht, impliziert dies hier, daß alle Wagen ohne * Zugpferde/-trolle als Fracht aufgeladen wurden: zu viele Pferde hat * die Einheit nicht zum Ziehen benutzt, also nicht mehr Wagen gezogen * als erlaubt. */ if (vehicles > maxwagen) return E_CANWALK_TOOMANYCARTS; - /* Es mu nicht zwingend an den Wagen liegen, aber egal... (man - * knnte z.B. auch 8 Eisen abladen, damit ein weiterer Wagen als - * Fracht draufpat) */ + /* Es muß nicht zwingend an den Wagen liegen, aber egal... (man + * könnte z.B. auch 8 Eisen abladen, damit ein weiterer Wagen als + * Fracht draufpasst) */ return E_CANWALK_TOOHEAVY; } @@ -660,7 +663,7 @@ int check_ship_allowed(struct ship *sh, const region * r) bt_harbour = bt_find("harbour"); if (sh->region && r_insectstalled(r)) { - /* insekten drfen nicht hier rein. haben wir welche? */ + /* insekten dürfen nicht hier rein. haben wir welche? */ unit *u; for (u = sh->region->units; u != NULL; u = u->next) { @@ -754,13 +757,13 @@ static void drifting_ships(region * r) sh->flags |= SF_FISHING; } - /* Schiff schon abgetrieben oder durch Zauber geschtzt? */ + /* Schiff schon abgetrieben oder durch Zauber geschützt? */ if (!drift || fval(sh, SF_DRIFTED) || is_cursed(sh->attribs, C_SHIP_NODRIFT, 0)) { shp = &sh->next; continue; } - /* Kapitn bestimmen */ + /* Kapitän bestimmen */ for (captain = r->units; captain; captain = captain->next) { if (captain->ship != sh) continue; @@ -770,8 +773,8 @@ static void drifting_ships(region * r) break; } } - /* Kapitn da? Beschdigt? Gengend Matrosen? - * Gengend leicht? Dann ist alles OK. */ + /* Kapitän da? Beschädigt? Genügend Matrosen? + * Genügend leicht? Dann ist alles OK. */ assert(sh->type->construction->improvement == NULL); /* sonst ist construction::size nicht ship_type::maxsize */ if (captain && sh->size == sh->type->construction->maxsize @@ -781,7 +784,7 @@ static void drifting_ships(region * r) } /* Auswahl einer Richtung: Zuerst auf Land, dann - * zufllig. Falls unmgliches Resultat: vergi es. */ + * zufällig. Falls unmögliches Resultat: vergiß es. */ d_offset = rng_int() % MAXDIRECTIONS; for (d = 0; d != MAXDIRECTIONS; ++d) { region *rn; @@ -919,17 +922,17 @@ static unit *bewegung_blockiert_von(unit * reisender, region * r) } if (guard) { prob += base_prob; /* 30% base chance */ - prob = +guard_count*guard_number_prob; + prob += guard_count*guard_number_prob; if (r->terrain == newterrain(T_GLACIER)) - prob = +region_type_prob * 2; + prob += region_type_prob * 2; if (r->terrain == newterrain(T_SWAMP)) - prob = +region_type_prob * 2; + prob += region_type_prob * 2; if (r->terrain == newterrain(T_MOUNTAIN)) - prob = +region_type_prob; + prob += region_type_prob; if (r->terrain == newterrain(T_VOLCANO)) - prob = +region_type_prob; + prob += region_type_prob; if (r->terrain == newterrain(T_VOLCANO_SMOKING)) - prob = +region_type_prob; + prob += region_type_prob; if (prob > 0 && chance(prob)) { return guard; @@ -981,7 +984,7 @@ static bool is_guardian_r(const unit * guard) return true; } -bool is_guard(const struct unit * u, int mask) +bool is_guard(const struct unit * u, unsigned int mask) { return is_guardian_r(u) && (getguard(u) & mask) != 0; } @@ -1137,7 +1140,8 @@ static const char *shortdirections[MAXDIRECTIONS] = { static void cycle_route(order * ord, unit * u, int gereist) { - int bytes, cm = 0; + size_t bytes; + int cm = 0; char tail[1024], *bufp = tail; char neworder[2048]; char token[128]; @@ -1177,11 +1181,11 @@ static void cycle_route(order * ord, unit * u, int gereist) if (!pause) { const char *loc = LOC(lang, shortdirections[d]); if (bufp != tail) { - bytes = (int)strlcpy(bufp, " ", size); + bytes = strlcpy(bufp, " ", size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } - bytes = (int)strlcpy(bufp, loc, size); + bytes = strlcpy(bufp, loc, size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } @@ -1190,10 +1194,10 @@ static void cycle_route(order * ord, unit * u, int gereist) break; else if (cm == gereist && !paused && pause) { const char *loc = LOC(lang, parameters[P_PAUSE]); - bytes = (int)strlcpy(bufp, " ", size); + bytes = strlcpy(bufp, " ", size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); - bytes = (int)strlcpy(bufp, loc, size); + bytes = strlcpy(bufp, loc, size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); paused = true; @@ -1331,7 +1335,9 @@ static bool roadto(const region * r, direction_t dir) region *r2; static const curse_type *roads_ct = NULL; - if (dir >= MAXDIRECTIONS || dir < 0) + assert(r); + assert(dir= MAXDIRECTIONS || dir < 0) return false; r2 = rconnect(r, dir); if (r == NULL || r2 == NULL) @@ -1472,16 +1478,16 @@ static void make_route(unit * u, order * ord, region_list ** routep) /** calculate the speed of a unit * - * zu Fu reist man 1 Region, zu Pferd 2 Regionen. Mit Straen reist - * man zu Fu 2, mit Pferden 3 weit. + * zu Fuß reist man 1 Region, zu Pferd 2 Regionen. Mit Straßen reist + * man zu Fuß 2, mit Pferden 3 weit. * - * Berechnet wird das mit BPs. Zu Fu hat man 4 BPs, zu Pferd 6. - * Normalerweise verliert man 3 BP pro Region, bei Straen nur 2 BP. - * Auerdem: Wenn Einheit transportiert, nur halbe BP + * Berechnet wird das mit BPs. Zu Fuß hat man 4 BPs, zu Pferd 6. + * Normalerweise verliert man 3 BP pro Region, bei Straßen nur 2 BP. + * Außerdem: Wenn Einheit transportiert, nur halbe BP */ static int movement_speed(unit * u) { - int mp; + int mp = BP_WALKING; static const curse_type *speed_ct; static bool init = false; double dk = u_race(u)->speed; @@ -1492,9 +1498,11 @@ static int movement_speed(unit * u) case RC_DRAGON: case RC_WYRM: case RC_FIREDRAGON: + return BP_DRAGON; case RC_BIRTHDAYDRAGON: case RC_SONGDRAGON: - return BP_DRAGON; + mp = BP_DRAGON; + break; default: break; } @@ -1512,7 +1520,6 @@ static int movement_speed(unit * u) } switch (canride(u)) { - case 1: /* Pferd */ mp = BP_RIDING; break; @@ -1522,8 +1529,6 @@ static int movement_speed(unit * u) break; default: - mp = BP_WALKING; - /* Siebenmeilentee */ if (get_effect(u, oldpotiontype[P_FAST]) >= u->number) { mp *= 2; @@ -1562,8 +1567,9 @@ static arg_regions *var_copy_regions(const region_list * begin, int size) if (size > 0) { int i = 0; + assert(size>0); arg_regions *dst = - (arg_regions *)malloc(sizeof(arg_regions) + sizeof(region *) * size); + (arg_regions *)malloc(sizeof(arg_regions) + sizeof(region *) * (size_t)size); dst->nregions = size; dst->regions = (region **)(dst + 1); for (rsrc = begin; i != size; rsrc = rsrc->next) { @@ -1617,7 +1623,7 @@ static const region_list *travel_route(unit * u, landing = true; } else if ((u_race(u)->flags & RCF_WALK) == 0) { - /* Spezialeinheiten, die nicht laufen knnen. */ + /* Spezialeinheiten, die nicht laufen können. */ ADDMSG(&u->faction->msgs, msg_message("detectocean", "unit region", u, next)); break; @@ -1630,7 +1636,7 @@ static const region_list *travel_route(unit * u, } } else { - /* Ozeanfelder knnen nur von Einheiten mit Schwimmen und ohne + /* Ozeanfelder können nur von Einheiten mit Schwimmen und ohne * Pferde betreten werden. */ if (!(canswim(u) || canfly(u))) { ADDMSG(&u->faction->msgs, msg_message("detectocean", @@ -1725,7 +1731,7 @@ static const region_list *travel_route(unit * u, walkmode = 2; } - /* Berichte ber Durchreiseregionen */ + /* Berichte über Durchreiseregionen */ if (mode != TRAVEL_TRANSPORTED) { arg_regions *ar = var_copy_regions(route_begin, steps - 1); @@ -1804,7 +1810,7 @@ buildingtype_exists(const region * r, const building_type * bt, bool working) return false; } -/* Prft, ob Ablegen von einer Kste in eine der erlaubten Richtungen erfolgt. */ +/* Prüft, ob Ablegen von einer Küste in eine der erlaubten Richtungen erfolgt. */ static bool check_takeoff(ship * sh, region * from, region * to) { @@ -1854,18 +1860,18 @@ sail(unit * u, order * ord, bool move_on_land, region_list ** routep) return; /* Wir suchen so lange nach neuen Richtungen, wie es geht. Diese werden - * dann nacheinander ausgefhrt. */ + * dann nacheinander ausgeführt. */ k = shipspeed(sh, u); last_point = starting_point; current_point = starting_point; - /* die nchste Region, in die man segelt, wird durch movewhere () aus der + /* die nächste Region, in die man segelt, wird durch movewhere () aus der * letzten Region bestimmt. * * Anfangen tun wir bei starting_point. next_point ist beim ersten - * Durchlauf schon gesetzt (Parameter!). current_point ist die letzte gltige, + * Durchlauf schon gesetzt (Parameter!). current_point ist die letzte gültige, * befahrene Region. */ while (next_point && current_point != next_point && step < k) { @@ -1885,18 +1891,13 @@ sail(unit * u, order * ord, bool move_on_land, region_list ** routep) if (!flying_ship(sh)) { int stormchance; - static int stormyness; - static int gamecookie = -1; + int stormyness = 0; int reason; - - if (gamecookie != global.cookie) { - bool storms_enabled = get_param_int(global.parameters, "rules.ship.storms", 1) != 0; - if (storms_enabled) { - gamedate date; - get_gamedate(turn, &date); - stormyness = storms ? storms[date.month] * 5 : 0; - } - gamecookie = global.cookie; + bool storms_enabled = get_param_int(global.parameters, "rules.ship.storms", 1) != 0; + if (storms_enabled) { + gamedate date; + get_gamedate(turn, &date); + stormyness = storms ? storms[date.month] * 5 : 0; } /* storms should be the first thing we do. */ @@ -1917,7 +1918,7 @@ sail(unit * u, order * ord, bool move_on_land, region_list ** routep) bool storm = true; int d_offset = rng_int() % MAXDIRECTIONS; direction_t d; - /* Sturm nur, wenn nchste Region Hochsee ist. */ + /* Sturm nur, wenn nächste Region Hochsee ist. */ for (d = 0; d != MAXDIRECTIONS; ++d) { direction_t dnext = (direction_t)((d + d_offset) % MAXDIRECTIONS); region *rn = rconnect(current_point, dnext); @@ -2053,16 +2054,16 @@ sail(unit * u, order * ord, bool move_on_land, region_list ** routep) sh = NULL; } - /* Nun enthlt current_point die Region, in der das Schiff seine Runde - * beendet hat. Wir generieren hier ein Ereignis fr den Spieler, das - * ihm sagt, bis wohin er gesegelt ist, falls er berhaupt vom Fleck - * gekommen ist. Das ist nicht der Fall, wenn er von der Kste ins + /* Nun enthält current_point die Region, in der das Schiff seine Runde + * beendet hat. Wir generieren hier ein Ereignis für den Spieler, das + * ihm sagt, bis wohin er gesegelt ist, falls er überhaupt vom Fleck + * gekommen ist. Das ist nicht der Fall, wenn er von der Küste ins * Inland zu segeln versuchte */ if (sh != NULL && fval(sh, SF_MOVED)) { unit *harbourmaster; /* nachdem alle Richtungen abgearbeitet wurden, und alle Einheiten - * transferiert wurden, kann der aktuelle Befehl gelscht werden. */ + * transferiert wurden, kann der aktuelle Befehl gelöscht werden. */ cycle_route(ord, u, step); set_order(&u->thisorder, NULL); if (!move_on_land) { @@ -2087,7 +2088,7 @@ sail(unit * u, order * ord, bool move_on_land, region_list ** routep) sh = move_ship(sh, starting_point, current_point, *routep); - /* Hafengebhren ? */ + /* Hafengebühren ? */ harbourmaster = owner_buildingtyp(current_point, bt_find("harbour")); if (sh && harbourmaster != NULL) { @@ -2129,20 +2130,6 @@ sail(unit * u, order * ord, bool move_on_land, region_list ** routep) } } -unit *get_captain(const ship * sh) -{ - const region *r = sh->region; - unit *u; - - for (u = r->units; u; u = u->next) { - if (u->ship == sh && u->number - && eff_skill(u, SK_SAILING, r) >= sh->type->cptskill) - return u; - } - - return NULL; -} - /* Segeln, Wandern, Reiten * when this routine returns a non-zero value, movement for the region needs * to be done again because of followers that got new MOVE orders. @@ -2310,10 +2297,11 @@ static void travel(unit * u, region_list ** routep) if (uf->region == r) { order *follow_order; const struct locale *lang = u->faction->locale; - + const char *s = LOC(uf->faction->locale, parameters[P_UNIT]); /* construct an order */ + assert(s || !"missing translation for UNIT keyword"); follow_order = create_order(K_FOLLOW, lang, "%s %i", - LOC(uf->faction->locale, parameters[P_UNIT]), ut->no); + s, ut->no); route_end = reroute(uf, route_begin, route_end); travel_i(uf, route_begin, route_end, follow_order, TRAVEL_FOLLOWING, @@ -2434,7 +2422,7 @@ static void piracy_cmd(unit * u, struct order *ord) /* Wenn nicht, sehen wir, ob wir ein Ziel finden. */ if (target_dir == NODIRECTION) { - /* Einheit ist also Kapitn. Jetzt gucken, in wievielen + /* Einheit ist also Kapitän. Jetzt gucken, in wievielen * Nachbarregionen potentielle Opfer sind. */ for (dir = 0; dir < MAXDIRECTIONS; dir++) { @@ -2493,7 +2481,7 @@ static void piracy_cmd(unit * u, struct order *ord) set_order(&u->thisorder, create_order(K_MOVE, u->faction->locale, "%s", LOC(u->faction->locale, directions[target_dir]))); - /* Bewegung ausfhren */ + /* Bewegung ausführen */ init_order(u->thisorder); move(u, true); } @@ -2532,7 +2520,8 @@ static direction_t hunted_dir(attrib * at, int id) static int hunt(unit * u, order * ord) { region *rc = u->region; - int bytes, moves, id, speed; + size_t bytes; + int moves, id, speed; char command[256], *bufp = command; size_t size = sizeof(command); direction_t dir; @@ -2577,7 +2566,7 @@ static int hunt(unit * u, order * ord) moves = 1; - speed = getuint(); + speed = (int)getuint(); if (speed == 0) { speed = shipspeed(u->ship, u); } @@ -2588,10 +2577,10 @@ static int hunt(unit * u, order * ord) } rc = rconnect(rc, dir); while (moves < speed && (dir = hunted_dir(rc->attribs, id)) != NODIRECTION) { - bytes = (int)strlcpy(bufp, " ", size); + bytes = strlcpy(bufp, " ", size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); - bytes = (int)strlcpy(bufp, LOC(u->faction->locale, directions[dir]), size); + bytes = strlcpy(bufp, LOC(u->faction->locale, directions[dir]), size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); moves++; @@ -2603,7 +2592,7 @@ static int hunt(unit * u, order * ord) /* NACH ignorieren und Parsing initialisieren. */ init_tokens_str(command); getstrtoken(); - /* NACH ausfhren */ + /* NACH ausführen */ move(u, false); return 1; /* true -> Einheitenliste von vorne durchgehen */ } @@ -2802,7 +2791,7 @@ void movement(void) if (repeat) continue; if (ships == 0) { - /* Abtreiben von beschdigten, unterbemannten, berladenen Schiffen */ + /* Abtreiben von beschädigten, unterbemannten, überladenen Schiffen */ drifting_ships(r); } r = r->next; diff --git a/src/move.h b/src/move.h index e3caf1fa9..f35012b07 100644 --- a/src/move.h +++ b/src/move.h @@ -39,15 +39,8 @@ extern "C" { #define MV_SWIM (1<<8) /* kann schwimmen */ #define MV_WALK (1<<9) /* kann ber Land gehen */ - /* Die tragekapaz. ist hardcodiert mit defines, da es bis jetzt sowieso nur 2 - ** objekte gibt, die etwas tragen. */ -#define SILVERWEIGHT 1 -#define SCALEWEIGHT 100 /* Faktor, um den die Anzeige von gewichten - * * skaliert wird */ -#define HORSECAPACITY 7000 -#define WAGONCAPACITY 14000 - #define HORSESNEEDED 2 +#define STRENGTHMULTIPLIER 50 /* multiplier for trollbelt */ /* ein mensch wiegt 10, traegt also 5, ein pferd wiegt 50, traegt also 20. ein ** wagen wird von zwei pferden gezogen und traegt total 140, davon 40 die @@ -67,11 +60,10 @@ extern "C" { void movement(void); void run_to(struct unit *u, struct region *to); struct unit *is_guarded(struct region *r, struct unit *u, unsigned int mask); - bool is_guard(const struct unit *u, int mask); + bool is_guard(const struct unit *u, unsigned int mask); int enoughsailors(const struct ship *sh, const struct region *r); bool canswim(struct unit *u); bool canfly(struct unit *u); - struct unit *get_captain(const struct ship *sh); void travelthru(const struct unit *u, struct region *r); struct ship *move_ship(struct ship *sh, struct region *from, struct region *to, struct region_list *route); diff --git a/src/move.test.c b/src/move.test.c index dbb82e571..4e2b5f41e 100644 --- a/src/move.test.c +++ b/src/move.test.c @@ -2,18 +2,22 @@ #include #include "move.h" +#include #include #include #include #include #include #include +#include #include +#include #include #include #include +#include static void test_ship_not_allowed_in_coast(CuTest * tc) { @@ -167,9 +171,54 @@ static void test_building_type_exists(CuTest * tc) CuAssertTrue(tc, !buildingtype_exists(r, btype2, false)); } +static void test_walkingcapacity(CuTest *tc) { + region *r; + unit *u; + int cap; + const struct item_type *itype; + + test_cleanup(); + test_create_world(); + + r = findregion(0, 0); + u = test_create_unit(test_create_faction(0), r); + cap = u->number * (u->_race->capacity + u->_race->weight); + CuAssertIntEquals(tc, cap, walkingcapacity(u)); + scale_number(u, 2); + cap = u->number * (u->_race->capacity + u->_race->weight); + CuAssertIntEquals(tc, cap, walkingcapacity(u)); + + itype = it_find("horse"); + assert(itype); + i_change(&u->items, itype, 1); + cap += itype->capacity; + CuAssertIntEquals(tc, cap, walkingcapacity(u)); + i_change(&u->items, itype, 1); + cap += itype->capacity; + CuAssertIntEquals(tc, cap, walkingcapacity(u)); + + itype = it_find("cart"); + assert(itype); + i_change(&u->items, itype, 1); + CuAssertIntEquals(tc, cap, walkingcapacity(u)); + set_level(u, SK_RIDING, 1); + cap += itype->capacity; + CuAssertIntEquals(tc, cap, walkingcapacity(u)); + + itype = test_create_itemtype("trollbelt"); + assert(itype); + i_change(&u->items, itype, 1); + CuAssertIntEquals(tc, cap + (STRENGTHMULTIPLIER-1) * u->_race->capacity, walkingcapacity(u)); + set_param(&global.parameters, "rules.trollbelt.multiplier", "5"); + CuAssertIntEquals(tc, cap + 4 * u->_race->capacity, walkingcapacity(u)); + + test_cleanup(); +} + CuSuite *get_move_suite(void) { CuSuite *suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_walkingcapacity); SUITE_ADD_TEST(suite, test_building_type_exists); SUITE_ADD_TEST(suite, test_ship_not_allowed_in_coast); SUITE_ADD_TEST(suite, test_ship_allowed_without_harbormaster); diff --git a/src/names.c b/src/names.c index dcd032f28..df2e5e0a6 100644 --- a/src/names.c +++ b/src/names.c @@ -215,7 +215,7 @@ const char *silbe3[SIL3] = { static const char *generic_name(const unit * u) { - const char * name = rc_name_s(u_race(u), (u->no == 1) ? NAME_SINGULAR : NAME_PLURAL); + const char * name = rc_name_s(u_race(u), (u->number == 1) ? NAME_SINGULAR : NAME_PLURAL); return LOC(u->faction->locale, name); } @@ -357,7 +357,8 @@ static const char *dracoid_name(const unit * u) static char name[NAMESIZE + 1]; // FIXME: static return value int mid_syllabels; - u = u; + /* ignore u */ + u = 0; /* Wieviele Mittelteile? */ mid_syllabels = rng_int() % 4; diff --git a/src/randenc.c b/src/randenc.c index 0a6042eec..12b1aec58 100644 --- a/src/randenc.c +++ b/src/randenc.c @@ -1126,6 +1126,7 @@ void randomevents(void) } else if (r->age > 20 && rng_int() % 100 < 8) { volcano_outbreak(r); + rsetterrain(r, T_VOLCANO); } } } @@ -1189,7 +1190,7 @@ void plagues(region * r) int dead = 0; peasants = rpeasants(r); - dead = (int)(0.5F + PLAGUE_VICTIMS * peasants); + dead = (int)(0.5 + PLAGUE_VICTIMS * peasants); for (i = dead; i != 0; i--) { if (rng_double() < PLAGUE_HEALCHANCE && rmoney(r) >= PLAGUE_HEALCOST) { rsetmoney(r, rmoney(r) - PLAGUE_HEALCOST); diff --git a/src/randenc.h b/src/randenc.h index 1f8ecf739..cc799db5f 100644 --- a/src/randenc.h +++ b/src/randenc.h @@ -25,9 +25,9 @@ extern "C" { struct region; /** Plagues **/ -#define PLAGUE_CHANCE 0.1F /* Seuchenwahrscheinlichkeit (siehe plagues()) */ -#define PLAGUE_VICTIMS 0.2F /* % Betroffene */ -#define PLAGUE_HEALCHANCE 0.25F /* Wahrscheinlichkeit Heilung */ +#define PLAGUE_CHANCE 0.1 /* Seuchenwahrscheinlichkeit (siehe plagues()) */ +#define PLAGUE_VICTIMS 0.2 /* % Betroffene */ +#define PLAGUE_HEALCHANCE 0.25 /* Wahrscheinlichkeit Heilung */ #define PLAGUE_HEALCOST 30 /* Heilkosten */ void plagues(struct region *r); void encounters(void); diff --git a/src/report.c b/src/report.c index 7b794e709..3d57ee4c2 100644 --- a/src/report.c +++ b/src/report.c @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 1998-2015, Enno Rehling Katja Zedel @@ -81,6 +81,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include #include +#include /* libc includes */ #include @@ -115,20 +116,20 @@ static char *gamedate_season(const struct locale *lang) return buf; } -void rpc(FILE * F, char c, size_t num) -{ +void newline(stream *out) { + sputs("", out); +} + +void write_spaces(stream *out, size_t num) { + static const char spaces[REPORTWIDTH] = " "; while (num > 0) { - putc(c, F); - num--; + size_t bytes = (num > REPORTWIDTH) ? REPORTWIDTH : num; + swrite(spaces, sizeof(char), bytes, out); + num -= bytes; } } -void rnl(FILE * F) -{ - fputc('\n', F); -} - -static void centre(FILE * F, const char *s, bool breaking) +static void centre(stream *out, const char *s, bool breaking) { /* Bei Namen die genau 80 Zeichen lang sind, kann es hier Probleme * geben. Seltsamerweise wird i dann auf MAXINT oder aehnlich @@ -140,39 +141,40 @@ static void centre(FILE * F, const char *s, bool breaking) sparagraph(&SP, s, 0, 0); T = SP; while (SP) { - centre(F, SP->s, false); + centre(out, SP->s, false); SP = SP->next; } freestrlist(T); } else { - rpc(F, ' ', (REPORTWIDTH - strlen(s) + 1) / 2); - fputs(s, F); - putc('\n', F); + write_spaces(out, (REPORTWIDTH - strlen(s) + 1) / 2); + sputs(s, out); } } static void -rparagraph(FILE * F, const char *str, ptrdiff_t indent, int hanging_indent, -char mark) +paragraph(stream *out, const char *str, ptrdiff_t indent, int hanging_indent, +char marker) { - static const char *spaces = " "; size_t length = REPORTWIDTH; - const char *end, *begin; + const char *end, *begin, *mark = 0; if (!str) return; /* find out if there's a mark + indent already encoded in the string. */ - if (!mark) { + if (!marker) { const char *x = str; while (*x == ' ') ++x; indent += x - str; if (x[0] && indent && x[1] == ' ') { indent += 2; - mark = x[0]; + mark = x; str = x + 2; hanging_indent -= 2; } + } + else { + mark = ▮ } begin = end = str; @@ -180,16 +182,16 @@ char mark) const char *last_space = begin; if (mark && indent >= 2) { - fwrite(spaces, sizeof(char), indent - 2, F); - fputc(mark, F); - fputc(' ', F); + write_spaces(out, indent - 2); + swrite(mark, sizeof(char), 1, out); + write_spaces(out, 1); mark = 0; } else if (begin == str) { - fwrite(spaces, sizeof(char), indent, F); + write_spaces(out, indent); } else { - fwrite(spaces, sizeof(char), indent + hanging_indent, F); + write_spaces(out, indent + hanging_indent); } while (*end && end <= begin + length - indent) { if (*end == ' ') { @@ -203,14 +205,14 @@ char mark) /* there was no space in this line. clip it */ last_space = end; } - fwrite(begin, sizeof(char), last_space - begin, F); + swrite(begin, sizeof(char), last_space - begin, out); begin = last_space; while (*begin == ' ') { ++begin; } if (begin > end) begin = end; - fputc('\n', F); + sputs("", out); } while (*begin); } @@ -229,7 +231,7 @@ static size_t write_spell_modifier(spell * sp, int flag, const char * str, bool return 0; } -static void nr_spell(FILE * F, spellbook_entry * sbe, const struct locale *lang) +static void nr_spell(stream *out, spellbook_entry * sbe, const struct locale *lang) { int bytes, k, itemanz, costtyp; char buf[4096]; @@ -238,11 +240,11 @@ static void nr_spell(FILE * F, spellbook_entry * sbe, const struct locale *lang) spell * sp = sbe->sp; const char *params = sp->parameter; - rnl(F); - centre(F, spell_name(sp, lang), true); - rnl(F); - rparagraph(F, LOC(lang, "nr_spell_description"), 0, 0, 0); - rparagraph(F, spell_info(sp, lang), 2, 0, 0); + newline(out); + centre(out, spell_name(sp, lang), true); + newline(out); + paragraph(out, LOC(lang, "nr_spell_description"), 0, 0, 0); + paragraph(out, spell_info(sp, lang), 2, 0, 0); bytes = (int)strlcpy(bufp, LOC(lang, "nr_spell_type"), size); if (wrptr(&bufp, &size, bytes) != 0) @@ -267,15 +269,15 @@ static void nr_spell(FILE * F, spellbook_entry * sbe, const struct locale *lang) if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); *bufp = 0; - rparagraph(F, buf, 0, 0, 0); + paragraph(out, buf, 0, 0, 0); sprintf(buf, "%s %d", LOC(lang, "nr_spell_level"), sbe->level); - rparagraph(F, buf, 0, 0, 0); + paragraph(out, buf, 0, 0, 0); sprintf(buf, "%s %d", LOC(lang, "nr_spell_rank"), sp->rank); - rparagraph(F, buf, 0, 0, 0); + paragraph(out, buf, 0, 0, 0); - rparagraph(F, LOC(lang, "nr_spell_components"), 0, 0, 0); + paragraph(out, LOC(lang, "nr_spell_components"), 0, 0, 0); for (k = 0; sp->components[k].type; ++k) { const resource_type *rtype = sp->components[k].type; itemanz = sp->components[k].amount; @@ -302,7 +304,7 @@ static void nr_spell(FILE * F, spellbook_entry * sbe, const struct locale *lang) } } *bufp = 0; - rparagraph(F, buf, 2, 2, '-'); + paragraph(out, buf, 2, 2, '-'); } } @@ -336,9 +338,8 @@ static void nr_spell(FILE * F, spellbook_entry * sbe, const struct locale *lang) } } *bufp = 0; - rparagraph(F, buf, 0, 0, 0); - - rparagraph(F, LOC(lang, "nr_spell_syntax"), 0, 0, 0); + paragraph(out, buf, 0, 0, 0); + paragraph(out, LOC(lang, "nr_spell_syntax"), 0, 0, 0); bufp = buf; size = sizeof(buf) - 1; @@ -505,77 +506,56 @@ static void nr_spell(FILE * F, spellbook_entry * sbe, const struct locale *lang) } } *bufp = 0; - rparagraph(F, buf, 2, 0, 0); - rnl(F); -} - -void sparagraph(strlist ** SP, const char *s, int indent, char mark) -{ - - /* Die Liste SP wird mit dem String s aufgefuellt, mit indent und einer - * mark, falls angegeben. SP wurde also auf 0 gesetzt vor dem Aufruf. - * Vgl. spunit (). */ - - int i, j, width; - int firstline; - static char buf[REPORTWIDTH + 1]; // FIXME: static return value - - width = REPORTWIDTH - indent; - firstline = 1; - - for (;;) { - i = 0; - - do { - j = i; - while (s[j] && s[j] != ' ') - j++; - if (j > width) { - - /* j zeigt auf das ende der aktuellen zeile, i zeigt auf den anfang der - * nchsten zeile. existiert ein wort am anfang der zeile, welches - * lnger als eine zeile ist, muss dieses hier abgetrennt werden. */ - - if (i == 0) - i = width - 1; - break; - } - i = j + 1; - } while (s[j]); - - for (j = 0; j != indent; j++) - buf[j] = ' '; - - if (firstline && mark) - buf[indent - 2] = mark; - - for (j = 0; j != i - 1; j++) - buf[indent + j] = s[j]; - buf[indent + j] = 0; - - addstrlist(SP, buf); - - if (s[i - 1] == 0) - break; - - s += i; - firstline = 0; - } + paragraph(out, buf, 2, 0, 0); + newline(out); } static void -nr_curses(FILE * F, const faction * viewer, const void *obj, objtype_t typ, -int indent) +nr_curses_i(stream *out, int indent, const faction *viewer, objtype_t typ, const void *obj, attrib *a, int self) +{ + for (; a; a = a->next) { + char buf[4096]; + message *msg; + + if (fval(a->type, ATF_CURSE)) { + curse *c = (curse *)a->data.v; + + if (c->type->cansee) { + self = c->type->cansee(viewer, obj, typ, c, self); + } + msg = msg_curse(c, obj, typ, self); + + if (msg) { + newline(out); + nr_render(msg, viewer->locale, buf, sizeof(buf), viewer); + paragraph(out, buf, indent, 2, 0); + msg_release(msg); + } + } + else if (a->type == &at_effect && self) { + effect_data *data = (effect_data *)a->data.v; + if (data->value > 0) { + msg = msg_message("nr_potion_effect", "potion left", + data->type->itype->rtype, data->value); + nr_render(msg, viewer->locale, buf, sizeof(buf), viewer); + paragraph(out, buf, indent, 2, 0); + msg_release(msg); + } + } + } +} + +static void nr_curses(stream *out, int indent, const faction *viewer, objtype_t typ, const void *obj) { - attrib *a = NULL; int self = 0; + attrib *a = NULL; region *r; /* Die Sichtbarkeit eines Zaubers und die Zaubermeldung sind bei - * Gebuden und Schiffen je nach, ob man Besitzer ist, verschieden. - * Bei Einheiten sieht man Wirkungen auf eigene Einheiten immer. - * Spezialflle (besonderes Talent, verursachender Magier usw. werde - * bei jedem curse gesondert behandelt. */ + * Gebäuden und Schiffen je nach, ob man Besitzer ist, verschieden. + * Bei Einheiten sieht man Wirkungen auf eigene Einheiten immer. + * Spezialfälle (besonderes Talent, verursachender Magier usw. werde + * bei jedem curse gesondert behandelt. */ if (typ == TYP_SHIP) { ship *sh = (ship *)obj; unit *owner = ship_owner(sh); @@ -629,47 +609,18 @@ int indent) a = r->attribs; } else { - /* fehler */ - } - - for (; a; a = a->next) { - char buf[4096]; - message *msg; - - if (fval(a->type, ATF_CURSE)) { - curse *c = (curse *)a->data.v; - - if (c->type->cansee) { - self = c->type->cansee(viewer, obj, typ, c, self); - } - msg = msg_curse(c, obj, typ, self); - - if (msg) { - rnl(F); - nr_render(msg, viewer->locale, buf, sizeof(buf), viewer); - rparagraph(F, buf, indent, 2, 0); - msg_release(msg); - } - } - else if (a->type == &at_effect && self) { - effect_data *data = (effect_data *)a->data.v; - if (data->value > 0) { - msg = msg_message("nr_potion_effect", "potion left", - data->type->itype->rtype, data->value); - nr_render(msg, viewer->locale, buf, sizeof(buf), viewer); - rparagraph(F, buf, indent, 2, 0); - msg_release(msg); - } - } + log_error("get_attribs: invalid object type %d", typ); + assert(!"invalid object type"); } + nr_curses_i(out, indent, viewer, typ, obj, a, self); } -static void rps_nowrap(FILE * F, const char *s) +static void rps_nowrap(stream *out, const char *s) { const char *x = s; size_t indent = 0; - if (!x) return; + if (!x || !*x) return; while (*x++ == ' '); indent = x - s - 1; @@ -682,12 +633,12 @@ static void rps_nowrap(FILE * F, const char *s) if (!x) x = s + strlen(s); } - rpc(F, *s++, 1); + swrite(s++, sizeof(char), 1, out); } } static void -nr_unit(FILE * F, const faction * f, const unit * u, int indent, int mode) +nr_unit(stream *out, const faction * f, const unit * u, int indent, int mode) { attrib *a_otherfaction; char marker; @@ -698,10 +649,8 @@ nr_unit(FILE * F, const faction * f, const unit * u, int indent, int mode) if (fval(u_race(u), RCF_INVISIBLE)) return; - { - rnl(F); - dh = bufunit(f, u, indent, mode, buf, sizeof(buf)); - } + newline(out); + dh = bufunit(f, u, indent, mode, buf, sizeof(buf)); a_otherfaction = a_find(u->attribs, &at_otherfaction); @@ -723,18 +672,19 @@ nr_unit(FILE * F, const faction * f, const unit * u, int indent, int mode) marker = '-'; } } - rparagraph(F, buf, indent, 0, marker); + paragraph(out, buf, indent, 0, marker); if (!isbattle) { - nr_curses(F, f, u, TYP_UNIT, indent); + nr_curses(out, indent, f, TYP_UNIT, u); } } static void -rp_messages(FILE * F, message_list * msgs, faction * viewer, int indent, +rp_messages(stream *out, message_list * msgs, faction * viewer, int indent, bool categorized) { nrsection *section; + if (!msgs) return; for (section = sections; section; section = section->next) { @@ -749,15 +699,15 @@ bool categorized) const char *section_title; char cat_identifier[24]; - rnl(F); + newline(out); sprintf(cat_identifier, "section_%s", section->name); section_title = LOC(viewer->locale, cat_identifier); - centre(F, section_title, true); - rnl(F); + centre(out, section_title, true); + newline(out); k = 1; } nr_render(m->msg, viewer->locale, lbuf, sizeof(lbuf), viewer); - rparagraph(F, lbuf, indent, 2, 0); + paragraph(out, lbuf, indent, 2, 0); } m = m->next; } @@ -766,27 +716,27 @@ bool categorized) } } -static void rp_battles(FILE * F, faction * f) +static void rp_battles(stream *out, faction * f) { if (f->battles != NULL) { struct bmsg *bm = f->battles; - rnl(F); - centre(F, LOC(f->locale, "section_battle"), false); - rnl(F); + newline(out); + centre(out, LOC(f->locale, "section_battle"), false); + newline(out); while (bm) { char buf[256]; RENDER(f, buf, sizeof(buf), ("battle::header", "region", bm->r)); - rnl(F); - centre(F, buf, true); - rnl(F); - rp_messages(F, bm->msgs, f, 0, false); + newline(out); + centre(out, buf, true); + newline(out); + rp_messages(out, bm->msgs, f, 0, false); bm = bm->next; } } } -static void prices(FILE * F, const region * r, const faction * f) +static void prices(stream *out, const region * r, const faction * f) { const luxury_type *sale = NULL; struct demand *dmd; @@ -838,7 +788,8 @@ static void prices(FILE * F, const region * r, const faction * f) size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); - } else if (n == 1) { + } + else if (n == 1) { bytes = (int)strlcpy(bufp, " ", size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); @@ -849,7 +800,8 @@ static void prices(FILE * F, const region * r, const faction * f) bytes = (int)strlcpy(bufp, " ", size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); - } else { + } + else { bytes = (int)strlcpy(bufp, LOC(f->locale, "nr_trade_next"), size); if (wrptr(&bufp, &size, bytes) != 0) @@ -863,8 +815,7 @@ static void prices(FILE * F, const region * r, const faction * f) } /* Schreibe Paragraphen */ *bufp = 0; - rparagraph(F, buf, 0, 0, 0); - + paragraph(out, buf, 0, 0, 0); } bool see_border(const connection * b, const faction * f, const region * r) @@ -887,9 +838,9 @@ bool see_border(const connection * b, const faction * f, const region * r) return cs; } -static void describe(FILE * F, const seen_region * sr, faction * f) +static void describe(stream *out, const seen_region * sr, faction * f) { - const region *r = sr->r; + const region *r; int n; bool dh; direction_t d; @@ -911,6 +862,11 @@ static void describe(FILE * F, const seen_region * sr, faction * f) size_t size = sizeof(buf); int bytes; + assert(out); + assert(f); + assert(sr); + + r = sr->r; for (d = 0; d != MAXDIRECTIONS; d++) { /* Nachbarregionen, die gesehen werden, ermitteln */ region *r2 = rconnect(r, d); @@ -1002,7 +958,7 @@ static void describe(FILE * F, const seen_region * sr, faction * f) } /* iron & stone */ - if (sr->mode == see_unit && f != (faction *)NULL) { + if (sr->mode == see_unit) { resource_report result[MAX_RAWMATERIALS]; int n, numresults = report_resources(sr, result, MAX_RAWMATERIALS, f); @@ -1196,9 +1152,9 @@ static void describe(FILE * F, const seen_region * sr, faction * f) dh = 1; } } - rnl(F); + newline(out); *bufp = 0; - rparagraph(F, buf, 0, 0, 0); + paragraph(out, buf, 0, 0, 0); if (sr->mode == see_unit && is_astral(r) && !is_cursed(r->attribs, C_ASTRALBLOCK, 0)) { @@ -1231,26 +1187,25 @@ static void describe(FILE * F, const seen_region * sr, faction * f) WARN_STATIC_BUFFER(); free_regionlist(rl); /* Schreibe Paragraphen */ - rnl(F); + newline(out); *bufp = 0; - rparagraph(F, buf, 0, 0, 0); + paragraph(out, buf, 0, 0, 0); } } + /* Wirkungen permanenter Sprüche */ + nr_curses(out, 0, f, TYP_REGION, r); n = 0; - /* Wirkungen permanenter Sprche */ - nr_curses(F, f, r, TYP_REGION, 0); - /* Produktionsreduktion */ a = a_find(r->attribs, &at_reduceproduction); if (a) { const char *str = LOC(f->locale, "nr_reduced_production"); - rparagraph(F, str, 0, 0, 0); + paragraph(out, str, 0, 0, 0); } if (edges) - rnl(F); + newline(out); for (e = edges; e; e = e->next) { bool first = true; message *msg; @@ -1283,7 +1238,7 @@ static void describe(FILE * F, const seen_region * sr, faction * f) WARN_STATIC_BUFFER(); *bufp = 0; - rparagraph(F, buf, 0, 0, 0); + paragraph(out, buf, 0, 0, 0); } if (edges) { while (edges) { @@ -1295,7 +1250,7 @@ static void describe(FILE * F, const seen_region * sr, faction * f) } } -static void statistics(FILE * F, const region * r, const faction * f) +static void statistics(stream *out, const region * r, const faction * f) { const unit *u; int number = 0, p = rpeasants(r); @@ -1313,19 +1268,19 @@ static void statistics(FILE * F, const region * r, const faction * f) } } /* print */ - rnl(F); + newline(out); m = msg_message("nr_stat_header", "region", r); nr_render(m, f->locale, buf, sizeof(buf), f); msg_release(m); - rparagraph(F, buf, 0, 0, 0); - rnl(F); + paragraph(out, buf, 0, 0, 0); + newline(out); /* Region */ if (skill_enabled(SK_ENTERTAINMENT) && fval(r->terrain, LAND_REGION) && rmoney(r)) { m = msg_message("nr_stat_maxentertainment", "max", entertainmoney(r)); nr_render(m, f->locale, buf, sizeof(buf), f); - rparagraph(F, buf, 2, 2, 0); + paragraph(out, buf, 2, 2, 0); msg_release(m); } if (production(r) && (!fval(r->terrain, SEA_REGION) @@ -1338,14 +1293,14 @@ static void statistics(FILE * F, const region * r, const faction * f) m = msg_message("nr_stat_salary", "max", wage(r, f, f->race, turn + 1)); } nr_render(m, f->locale, buf, sizeof(buf), f); - rparagraph(F, buf, 2, 2, 0); + paragraph(out, buf, 2, 2, 0); msg_release(m); } if (p) { m = msg_message("nr_stat_recruits", "max", p / RECRUITFRACTION); nr_render(m, f->locale, buf, sizeof(buf), f); - rparagraph(F, buf, 2, 2, 0); + paragraph(out, buf, 2, 2, 0); msg_release(m); if (!markets_module()) { @@ -1356,14 +1311,14 @@ static void statistics(FILE * F, const region * r, const faction * f) m = msg_message("nr_stat_luxuries", "max", p / TRADE_FRACTION); } nr_render(m, f->locale, buf, sizeof(buf), f); - rparagraph(F, buf, 2, 2, 0); + paragraph(out, buf, 2, 2, 0); msg_release(m); } if (r->land->ownership) { m = msg_message("nr_stat_morale", "morale", r->land->morale); nr_render(m, f->locale, buf, sizeof(buf), f); - rparagraph(F, buf, 2, 2, 0); + paragraph(out, buf, 2, 2, 0); msg_release(m); } @@ -1372,19 +1327,19 @@ static void statistics(FILE * F, const region * r, const faction * f) m = msg_message("nr_stat_people", "max", number); nr_render(m, f->locale, buf, sizeof(buf), f); - rparagraph(F, buf, 2, 2, 0); + paragraph(out, buf, 2, 2, 0); msg_release(m); for (itm = items; itm; itm = itm->next) { sprintf(buf, "%s: %d", LOC(f->locale, resourcename(itm->type->rtype, GR_PLURAL)), itm->number); - rparagraph(F, buf, 2, 2, 0); + paragraph(out, buf, 2, 2, 0); } while (items) i_free(i_remove(&items, items)); } -static void durchreisende(FILE * F, const region * r, const faction * f) +static void durchreisende(stream *out, const region * r, const faction * f) { if (fval(r, RF_TRAVELUNIT)) { attrib *abegin = a_find(r->attribs, &at_travelunit), *a; @@ -1410,7 +1365,7 @@ static void durchreisende(FILE * F, const region * r, const faction * f) } /* Auflisten. */ - rnl(F); + newline(out); for (a = abegin; a && a->type == &at_travelunit; a = a->next) { unit *u = (unit *)a->data.v; @@ -1419,48 +1374,33 @@ static void durchreisende(FILE * F, const region * r, const faction * f) if (cansee_durchgezogen(f, r, u, 0)) { ++counter; if (u->ship != NULL) { -#ifdef GERMAN_FLUFF_ENABLED - if (strcmp("de", f->locale->name)==0) { - if (counter == 1) { - bytes = (int)strlcpy(bufp, "Die ", size); - } - else { - bytes = (int)strlcpy(bufp, "die ", size); - } - if (wrptr(&bufp, &size, bytes) != 0) { - WARN_STATIC_BUFFER(); - break; - } - } -#endif bytes = (int)strlcpy(bufp, shipname(u->ship), size); } else { bytes = (int)strlcpy(bufp, unitname(u), size); } if (wrptr(&bufp, &size, bytes) != 0) { - WARN_STATIC_BUFFER(); + INFO_STATIC_BUFFER(); break; } if (counter + 1 < maxtravel) { bytes = (int)strlcpy(bufp, ", ", size); if (wrptr(&bufp, &size, bytes) != 0) { - WARN_STATIC_BUFFER(); + INFO_STATIC_BUFFER(); break; } } else if (counter + 1 == maxtravel) { bytes = (int)strlcpy(bufp, LOC(f->locale, "list_and"), size); if (wrptr(&bufp, &size, bytes) != 0) { - WARN_STATIC_BUFFER(); + INFO_STATIC_BUFFER(); break; } } } } } - /* TODO: finish localization */ if (size > 0) { if (maxtravel == 1) { bytes = _snprintf(bufp, size, " %s", LOC(f->locale, "has_moved_one")); @@ -1472,7 +1412,7 @@ static void durchreisende(FILE * F, const region * r, const faction * f) WARN_STATIC_BUFFER(); } *bufp = 0; - rparagraph(F, buf, 0, 0, 0); + paragraph(out, buf, 0, 0, 0); } } @@ -1508,6 +1448,7 @@ report_template(const char *filename, report_context * ctx, const char *charset) faction *f = ctx->f; region *r; FILE *F = fopen(filename, "wt"); + stream strm = { 0 }, *out = &strm; seen_region *sr = NULL; char buf[8192], *bufp; size_t size; @@ -1518,31 +1459,26 @@ report_template(const char *filename, report_context * ctx, const char *charset) perror(filename); return -1; } + fstream_init(&strm, F); if (utf8) { const unsigned char utf8_bom[4] = { 0xef, 0xbb, 0xbf, 0 }; - fwrite(utf8_bom, 1, 3, F); + swrite(utf8_bom, 1, 3, out); } - rps_nowrap(F, ""); - rnl(F); - rps_nowrap(F, LOC(f->locale, "nr_template")); - rnl(F); - rps_nowrap(F, ""); - rnl(F); + newline(out); + rps_nowrap(out, LOC(f->locale, "nr_template")); + newline(out); + newline(out); - sprintf(buf, "%s %s \"%s\"", LOC(f->locale, "ERESSEA"), factionid(f), - LOC(f->locale, "enterpasswd")); - rps_nowrap(F, buf); - rnl(F); - - rps_nowrap(F, ""); - rnl(F); + sprintf(buf, "%s %s \"%s\"", LOC(f->locale, "ERESSEA"), factionid(f), f->passw); + rps_nowrap(out, buf); + newline(out); + newline(out); sprintf(buf, "; ECHECK -l -w4 -r%d -v%s", f->race->recruitcost, ECHECK_VERSION); - /* -v3.4: ECheck Version 3.4.x */ - rps_nowrap(F, buf); - rnl(F); + rps_nowrap(out, buf); + newline(out); for (r = ctx->first; sr == NULL && r != ctx->last; r = r->next) { sr = find_seen(ctx->seen, r); @@ -1564,9 +1500,8 @@ report_template(const char *filename, report_context * ctx, const char *charset) int nx = r->x, ny = r->y; pnormalize(&nx, &ny, pl); - adjust_coordinates(f, &nx, &ny, pl, r); - rps_nowrap(F, ""); - rnl(F); + adjust_coordinates(f, &nx, &ny, pl); + newline(out); if (pl && pl->id != 0) { sprintf(buf, "%s %d,%d,%d ; %s", LOC(f->locale, parameters[P_REGION]), nx, ny, pl->id, rname(r, f->locale)); @@ -1575,13 +1510,12 @@ report_template(const char *filename, report_context * ctx, const char *charset) sprintf(buf, "%s %d,%d ; %s", LOC(f->locale, parameters[P_REGION]), nx, ny, rname(r, f->locale)); } - rps_nowrap(F, buf); - rnl(F); + rps_nowrap(out, buf); + newline(out); sprintf(buf, "; ECheck Lohn %d", wage(r, f, f->race, turn + 1)); - rps_nowrap(F, buf); - rnl(F); - rps_nowrap(F, ""); - rnl(F); + rps_nowrap(out, buf); + newline(out); + newline(out); } dh = 1; @@ -1589,7 +1523,7 @@ report_template(const char *filename, report_context * ctx, const char *charset) size = sizeof(buf) - 1; bytes = _snprintf(bufp, size, "%s %s; %s [%d,%d$", LOC(u->faction->locale, parameters[P_UNIT]), - unitid(u), u->name, u->number, get_money(u)); + unitid(u), unit_getname(u), u->number, get_money(u)); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); if (u->building && building_owner(u->building) == u) { @@ -1628,24 +1562,25 @@ report_template(const char *filename, report_context * ctx, const char *charset) WARN_STATIC_BUFFER(); *bufp = 0; - rps_nowrap(F, buf); - rnl(F); + rps_nowrap(out, buf); + newline(out); for (ord = u->old_orders; ord; ord = ord->next) { /* this new order will replace the old defaults */ strcpy(buf, " "); write_order(ord, buf + 2, sizeof(buf) - 2); - rps_nowrap(F, buf); - rnl(F); + rps_nowrap(out, buf); + newline(out); } for (ord = u->orders; ord; ord = ord->next) { - if (u->old_orders && is_repeated(ord)) + keyword_t kwd = getkeyword(ord); + if (u->old_orders && is_repeated(kwd)) continue; /* unit has defaults */ if (is_persistent(ord)) { strcpy(buf, " "); write_order(ord, buf + 2, sizeof(buf) - 2); - rps_nowrap(F, buf); - rnl(F); + rps_nowrap(out, buf); + newline(out); } } @@ -1654,12 +1589,11 @@ report_template(const char *filename, report_context * ctx, const char *charset) } } } - rps_nowrap(F, ""); - rnl(F); + newline(out); strcpy(buf, LOC(f->locale, parameters[P_NEXT])); - rps_nowrap(F, buf); - rnl(F); - fclose(F); + rps_nowrap(out, buf); + newline(out); + fstream_done(&strm); return 0; } @@ -1756,7 +1690,7 @@ show_allies(const faction * f, const ally * allies, char *buf, size_t size) *bufp = 0; } -static void allies(FILE * F, const faction * f) +static void allies(stream *out, const faction * f) { const group *g = f->groups; char buf[16384]; @@ -1767,8 +1701,8 @@ static void allies(FILE * F, const faction * f) bytes = _snprintf(buf, size, "%s ", LOC(f->locale, "faction_help")); size -= bytes; show_allies(f, f->allies, buf + bytes, size); - rparagraph(F, buf, 0, 0, 0); - rnl(F); + paragraph(out, buf, 0, 0, 0); + newline(out); } while (g) { @@ -1778,25 +1712,21 @@ static void allies(FILE * F, const faction * f) bytes = _snprintf(buf, size, "%s %s ", g->name, LOC(f->locale, "group_help")); size -= bytes; show_allies(f, g->allies, buf + bytes, size); - rparagraph(F, buf, 0, 0, 0); - rnl(F); + paragraph(out, buf, 0, 0, 0); + newline(out); } g = g->next; } } -static void guards(FILE * F, const region * r, const faction * see) +static void guards(stream *out, const region * r, const faction * see) { /* die Partei see sieht dies; wegen * "unbekannte Partei", wenn man es selbst ist... */ - faction *guardians[512]; - int nextguard = 0; - unit *u; int i; - bool tarned = false; /* Bewachung */ @@ -1856,29 +1786,29 @@ static void guards(FILE * F, const region * r, const faction * see) bytes = (int)strlcpy(bufp, LOC(see->locale, "nr_guarding_postfix"), size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); - rnl(F); + newline(out); *bufp = 0; - rparagraph(F, buf, 0, 0, 0); + paragraph(out, buf, 0, 0, 0); } } -static void rpline(FILE * F) +static void rpline(stream *out) { static char line[REPORTWIDTH + 1]; if (line[0] != '-') { memset(line, '-', sizeof(line)); line[REPORTWIDTH] = '\n'; } - fwrite(line, sizeof(char), sizeof(line), F); + swrite(line, sizeof(char), sizeof(line), out); } -static void list_address(FILE * F, const faction * uf, quicklist * seenfactions) +static void list_address(stream *out, const faction * uf, quicklist * seenfactions) { int qi = 0; quicklist *flist = seenfactions; - centre(F, LOC(uf->locale, "nr_addresses"), false); - rnl(F); + centre(out, LOC(uf->locale, "nr_addresses"), false); + newline(out); while (flist != NULL) { const faction *f = (const faction *)ql_get(flist, qi); @@ -1894,17 +1824,16 @@ static void list_address(FILE * F, const faction * uf, quicklist * seenfactions) label = 'o'; else if (alliedfaction(NULL, uf, f, HELP_ALL)) label = '+'; - rparagraph(F, buf, 4, 0, label); - + paragraph(out, buf, 4, 0, label); } ql_advance(&flist, &qi, 1); } - rnl(F); - rpline(F); + newline(out); + rpline(out); } static void -nr_ship(FILE * F, const seen_region * sr, const ship * sh, const faction * f, +nr_ship(stream *out, const seen_region * sr, const ship * sh, const faction * f, const unit * captain) { const region *r = sr->r; @@ -1913,7 +1842,7 @@ const unit * captain) int bytes; char ch; - rnl(F); + newline(out); if (captain && captain->faction == f) { int n = 0, p = 0; @@ -1973,13 +1902,13 @@ const unit * captain) WARN_STATIC_BUFFER(); } *bufp = 0; - rparagraph(F, buffer, 2, 0, 0); + paragraph(out, buffer, 2, 0, 0); - nr_curses(F, f, sh, TYP_SHIP, 4); + nr_curses(out, 4, f, TYP_SHIP, sh); } static void -nr_building(FILE * F, const seen_region * sr, const building * b, +nr_building(stream *out, const seen_region * sr, const building * b, const faction * f) { int i, bytes; @@ -1989,7 +1918,7 @@ const faction * f) message *msg; size_t size = sizeof(buffer) - 1; - rnl(F); + newline(out); if (f) lang = f->locale; @@ -2047,15 +1976,16 @@ const faction * f) WARN_STATIC_BUFFER(); } *bufp = 0; - rparagraph(F, buffer, 2, 0, 0); + paragraph(out, buffer, 2, 0, 0); if (sr->mode < see_lighthouse) return; - nr_curses(F, f, b, TYP_BUILDING, 4); + i = 0; + nr_curses(out, 4, f, TYP_BUILDING, b); } -static void nr_paragraph(FILE * F, message * m, faction * f) +static void nr_paragraph(stream *out, message * m, faction * f) { int bytes; char buf[4096], *bufp = buf; @@ -2066,7 +1996,7 @@ static void nr_paragraph(FILE * F, message * m, faction * f) WARN_STATIC_BUFFER(); msg_release(m); - rparagraph(F, buf, 0, 0, 0); + paragraph(out, buf, 0, 0, 0); } int @@ -2083,9 +2013,10 @@ const char *charset) attrib *a; message *m; unsigned char op; - int bytes, ix = want(O_STATISTICS); + int maxh, bytes, ix = want(O_STATISTICS); int wants_stats = (f->options & ix); FILE *F = fopen(filename, "wt"); + stream strm = { 0 }, *out = &strm; seen_region *sr = NULL; char buf[8192]; char *bufp; @@ -2109,6 +2040,8 @@ const char *charset) perror(filename); return -1; } + fstream_init(&strm, F); + if (utf8) { const unsigned char utf8_bom[4] = { 0xef, 0xbb, 0xbf, 0 }; fwrite(utf8_bom, 1, 3, F); @@ -2118,16 +2051,16 @@ const char *charset) m = msg_message("nr_header_date", "game date", game_name(), pzTime); nr_render(m, f->locale, buf, sizeof(buf), f); msg_release(m); - centre(F, buf, true); + centre(out, buf, true); - centre(F, gamedate_season(f->locale), true); - rnl(F); + centre(out, gamedate_season(f->locale), true); + newline(out); sprintf(buf, "%s, %s/%s (%s)", factionname(f), LOC(f->locale, rc_name_s(f->race, NAME_PLURAL)), LOC(f->locale, mkname("school", magic_school[f->magiegebiet])), f->email); - centre(F, buf, true); + centre(out, buf, true); if (f_get_alliance(f)) { - centre(F, alliancename(f->alliance), true); + centre(out, alliancename(f->alliance), true); } if (f->age <= 2) { @@ -2136,33 +2069,33 @@ const char *charset) ADDMSG(&f->msgs, msg_message("changepasswd", "value", f->passw)); } RENDER(f, buf, sizeof(buf), ("newbie_password", "password", f->passw)); - rnl(F); - centre(F, buf, true); + newline(out); + centre(out, buf, true); s = locale_getstring(f->locale, "newbie_info_1"); if (s) { - rnl(F); - centre(F, s, true); + newline(out); + centre(out, s, true); } s = locale_getstring(f->locale, "newbie_info_2"); if (s) { - rnl(F); - centre(F, s, true); + newline(out); + centre(out, s, true); } if ((f->options & want(O_COMPUTER)) == 0) { f->options |= want(O_COMPUTER); s = locale_getstring(f->locale, "newbie_info_3"); if (s) { - rnl(F); - centre(F, s, true); + newline(out); + centre(out, s, true); } } } - rnl(F); + newline(out); #if SCORE_MODULE if (f->options & want(O_SCORE) && f->age > DISPLAYSCORE) { RENDER(f, buf, sizeof(buf), ("nr_score", "score average", f->score, average_score_of_age(f->age, f->age / 24 + 1))); - centre(F, buf, true); + centre(out, buf, true); } #endif #ifdef COUNT_AGAIN @@ -2194,7 +2127,7 @@ const char *charset) m = msg_message("nr_population", "population units limit", no_people, no_units, rule_faction_limit()); nr_render(m, f->locale, buf, sizeof(buf), f); msg_release(m); - centre(F, buf, true); + centre(out, buf, true); if (f->race == get_race(RC_HUMAN)) { int maxmig = count_maxmigrants(f); if (maxmig > 0) { @@ -2202,7 +2135,7 @@ const char *charset) msg_message("nr_migrants", "units maxunits", count_migrants(f), maxmig); nr_render(m, f->locale, buf, sizeof(buf), f); msg_release(m); - centre(F, buf, true); + centre(out, buf, true); } } if (f_get_alliance(f)) { @@ -2212,268 +2145,266 @@ const char *charset) turn - f->alliance_joindate); nr_render(m, f->locale, buf, sizeof(buf), f); msg_release(m); - centre(F, buf, true); + centre(out, buf, true); + } + maxh = maxheroes(f); + if (maxh) { + message *msg = + msg_message("nr_heroes", "units maxunits", countheroes(f), maxh); + nr_render(msg, f->locale, buf, sizeof(buf), f); + msg_release(msg); + centre(out, buf, true); } - { - int maxh = maxheroes(f); - if (maxh) { - message *msg = - msg_message("nr_heroes", "units maxunits", countheroes(f), maxh); - nr_render(msg, f->locale, buf, sizeof(buf), f); - msg_release(msg); - centre(F, buf, true); - } - } - if (f->items != NULL) { - message *msg = msg_message("nr_claims", "items", f->items); - nr_render(msg, f->locale, buf, sizeof(buf), f); - msg_release(msg); - rnl(F); - centre(F, buf, true); - } + if (f->items != NULL) { + message *msg = msg_message("nr_claims", "items", f->items); + nr_render(msg, f->locale, buf, sizeof(buf), f); + msg_release(msg); + newline(out); + centre(out, buf, true); + } - /* Insekten-Winter-Warnung */ - if (f->race == get_race(RC_INSECT)) { - if (thisseason == 0) { - centre(F, LOC(f->locale, "nr_insectwinter"), true); - rnl(F); - } - else { - if (nextseason == 0) { - centre(F, LOC(f->locale, "nr_insectfall"), true); - rnl(F); - } - } - } + /* Insekten-Winter-Warnung */ + if (f->race == get_race(RC_INSECT)) { + if (thisseason == 0) { + centre(out, LOC(f->locale, "nr_insectwinter"), true); + newline(out); + } + else { + if (nextseason == 0) { + centre(out, LOC(f->locale, "nr_insectfall"), true); + newline(out); + } + } + } - bufp = buf; - size = sizeof(buf) - 1; - bytes = _snprintf(buf, size, "%s:", LOC(f->locale, "nr_options")); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); - for (op = 0; op != MAXOPTIONS; op++) { - if (f->options & want(op) && options[op]) { - bytes = (int)strlcpy(bufp, " ", size); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); - bytes = (int)strlcpy(bufp, LOC(f->locale, options[op]), size); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); + bufp = buf; + size = sizeof(buf) - 1; + bytes = _snprintf(buf, size, "%s:", LOC(f->locale, "nr_options")); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); + for (op = 0; op != MAXOPTIONS; op++) { + if (f->options & want(op) && options[op]) { + bytes = (int)strlcpy(bufp, " ", size); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); + bytes = (int)strlcpy(bufp, LOC(f->locale, options[op]), size); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); - flag++; - } - } - if (flag > 0) { - rnl(F); - *bufp = 0; - centre(F, buf, true); - } + flag++; + } + } + if (flag > 0) { + newline(out); + *bufp = 0; + centre(out, buf, true); + } - rp_messages(F, f->msgs, f, 0, true); - rp_battles(F, f); - a = a_find(f->attribs, &at_reportspell); - if (a) { - rnl(F); - centre(F, LOC(f->locale, "section_newspells"), true); - while (a && a->type == &at_reportspell) { - spellbook_entry *sbe = (spellbook_entry *)a->data.v; - nr_spell(F, sbe, f->locale); - a = a->next; - } - } + rp_messages(out, f->msgs, f, 0, true); + rp_battles(out, f); + a = a_find(f->attribs, &at_reportspell); + if (a) { + newline(out); + centre(out, LOC(f->locale, "section_newspells"), true); + while (a && a->type == &at_reportspell) { + spellbook_entry *sbe = (spellbook_entry *)a->data.v; + nr_spell(out, sbe, f->locale); + a = a->next; + } + } - ch = 0; - for (a = a_find(f->attribs, &at_showitem); a && a->type == &at_showitem; - a = a->next) { - const potion_type *ptype = - resource2potion(((const item_type *)a->data.v)->rtype); - const char *description = NULL; - if (ptype != NULL) { - const char *pname = resourcename(ptype->itype->rtype, 0); + ch = 0; + for (a = a_find(f->attribs, &at_showitem); a && a->type == &at_showitem; + a = a->next) { + const potion_type *ptype = + resource2potion(((const item_type *)a->data.v)->rtype); + const char *description = NULL; + if (ptype != NULL) { + const char *pname = resourcename(ptype->itype->rtype, 0); - if (ch == 0) { - rnl(F); - centre(F, LOC(f->locale, "section_newpotions"), true); - ch = 1; - } + if (ch == 0) { + newline(out); + centre(out, LOC(f->locale, "section_newpotions"), true); + ch = 1; + } - rnl(F); - centre(F, LOC(f->locale, pname), true); - _snprintf(buf, sizeof(buf), "%s %d", LOC(f->locale, "nr_level"), - ptype->level); - centre(F, buf, true); - rnl(F); + newline(out); + centre(out, LOC(f->locale, pname), true); + _snprintf(buf, sizeof(buf), "%s %d", LOC(f->locale, "nr_level"), + ptype->level); + centre(out, buf, true); + newline(out); - bufp = buf; - size = sizeof(buf) - 1; - bytes = _snprintf(bufp, size, "%s: ", LOC(f->locale, "nr_herbsrequired")); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); + bufp = buf; + size = sizeof(buf) - 1; + bytes = _snprintf(bufp, size, "%s: ", LOC(f->locale, "nr_herbsrequired")); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); - if (ptype->itype->construction) { - requirement *m = ptype->itype->construction->materials; - while (m->number) { - bytes = - (int)strlcpy(bufp, LOC(f->locale, resourcename(m->rtype, 0)), size); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); - ++m; - if (m->number) - bytes = (int)strlcpy(bufp, ", ", size); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); - } - } - *bufp = 0; - centre(F, buf, true); - rnl(F); - if (description == NULL) { - const char *potiontext = mkname("potion", pname); - description = LOC(f->locale, potiontext); - } - centre(F, description, true); - } - } - rnl(F); - centre(F, LOC(f->locale, "nr_alliances"), false); - rnl(F); + if (ptype->itype->construction) { + requirement *m = ptype->itype->construction->materials; + while (m->number) { + bytes = + (int)strlcpy(bufp, LOC(f->locale, resourcename(m->rtype, 0)), size); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); + ++m; + if (m->number) + bytes = (int)strlcpy(bufp, ", ", size); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); + } + } + *bufp = 0; + centre(out, buf, true); + newline(out); + if (description == NULL) { + const char *potiontext = mkname("potion", pname); + description = LOC(f->locale, potiontext); + } + centre(out, description, true); + } + } + newline(out); + centre(out, LOC(f->locale, "nr_alliances"), false); + newline(out); - allies(F, f); + allies(out, f); - rpline(F); + rpline(out); - anyunits = 0; + anyunits = 0; - for (r = ctx->first; sr == NULL && r != ctx->last; r = r->next) { - sr = find_seen(ctx->seen, r); - } - for (; sr != NULL; sr = sr->next) { - region *r = sr->r; - int stealthmod = stealth_modifier(sr->mode); - building *b = r->buildings; - ship *sh = r->ships; + for (r = ctx->first; sr == NULL && r != ctx->last; r = r->next) { + sr = find_seen(ctx->seen, r); + } + for (; sr != NULL; sr = sr->next) { + region *r = sr->r; + int stealthmod = stealth_modifier(sr->mode); + building *b = r->buildings; + ship *sh = r->ships; - if (sr->mode < see_lighthouse) - continue; - /* Beschreibung */ + if (sr->mode < see_lighthouse) + continue; + /* Beschreibung */ - if (sr->mode == see_unit) { - anyunits = 1; - describe(F, sr, f); - if (markets_module() && r->land) { - const item_type *lux = r_luxury(r); - const item_type *herb = r->land->herbtype; - message *m = 0; - if (herb && lux) { - m = msg_message("nr_market_info_p", "p1 p2", - lux ? lux->rtype : 0, herb ? herb->rtype : 0); - } - else if (lux || herb) { - m = msg_message("nr_market_info_s", "p1", - lux ? lux->rtype : herb->rtype); - } - if (m) { - rnl(F); - nr_paragraph(F, m, f); - } - /* */ - } - else { - if (!fval(r->terrain, SEA_REGION) && rpeasants(r) / TRADE_FRACTION > 0) { - rnl(F); - prices(F, r, f); - } - } - guards(F, r, f); - durchreisende(F, r, f); - } - else { - if (sr->mode == see_far) { - describe(F, sr, f); - guards(F, r, f); - durchreisende(F, r, f); - } - else if (sr->mode == see_lighthouse) { - describe(F, sr, f); - durchreisende(F, r, f); - } - else { - describe(F, sr, f); - durchreisende(F, r, f); - } - } - /* Statistik */ + if (sr->mode == see_unit) { + anyunits = 1; + describe(out, sr, f); + if (markets_module() && r->land) { + const item_type *lux = r_luxury(r); + const item_type *herb = r->land->herbtype; + message *m = 0; + if (herb && lux) { + m = msg_message("nr_market_info_p", "p1 p2", + lux ? lux->rtype : 0, herb ? herb->rtype : 0); + } + else if (lux || herb) { + m = msg_message("nr_market_info_s", "p1", + lux ? lux->rtype : herb->rtype); + } + if (m) { + newline(out); + nr_paragraph(out, m, f); + } + /* */ + } + else { + if (!fval(r->terrain, SEA_REGION) && rpeasants(r) / TRADE_FRACTION > 0) { + newline(out); + prices(out, r, f); + } + } + guards(out, r, f); + durchreisende(out, r, f); + } + else { + if (sr->mode == see_far) { + describe(out, sr, f); + guards(out, r, f); + durchreisende(out, r, f); + } + else if (sr->mode == see_lighthouse) { + describe(out, sr, f); + durchreisende(out, r, f); + } + else { + describe(out, sr, f); + durchreisende(out, r, f); + } + } + /* Statistik */ - if (wants_stats && sr->mode == see_unit) - statistics(F, r, f); + if (wants_stats && sr->mode == see_unit) + statistics(out, r, f); - /* Nachrichten an REGION in der Region */ + /* Nachrichten an REGION in der Region */ - if (sr->mode == see_unit || sr->mode == see_travel) { - // TODO: Bug 2073 - message_list *mlist = r_getmessages(r, f); - rp_messages(F, r->msgs, f, 0, true); - if (mlist) - rp_messages(F, mlist, f, 0, true); - } + if (sr->mode == see_unit || sr->mode == see_travel) { + // TODO: Bug 2073 + message_list *mlist = r_getmessages(r, f); + rp_messages(out, r->msgs, f, 0, true); + if (mlist) + rp_messages(out, mlist, f, 0, true); + } - /* report all units. they are pre-sorted in an efficient manner */ - u = r->units; - while (b) { - while (b && (!u || u->building != b)) { - nr_building(F, sr, b, f); - b = b->next; - } - if (b) { - nr_building(F, sr, b, f); - while (u && u->building == b) { - nr_unit(F, f, u, 6, sr->mode); - u = u->next; - } - b = b->next; - } - } - while (u && !u->ship) { - if (stealthmod > INT_MIN) { - if (u->faction == f || cansee(f, r, u, stealthmod)) { - nr_unit(F, f, u, 4, sr->mode); - } - } - assert(!u->building); - u = u->next; - } - while (sh) { - while (sh && (!u || u->ship != sh)) { - nr_ship(F, sr, sh, f, NULL); - sh = sh->next; - } - if (sh) { - nr_ship(F, sr, sh, f, u); - while (u && u->ship == sh) { - nr_unit(F, f, u, 6, sr->mode); - u = u->next; - } - sh = sh->next; - } - } + /* report all units. they are pre-sorted in an efficient manner */ + u = r->units; + while (b) { + while (b && (!u || u->building != b)) { + nr_building(out, sr, b, f); + b = b->next; + } + if (b) { + nr_building(out, sr, b, f); + while (u && u->building == b) { + nr_unit(out, f, u, 6, sr->mode); + u = u->next; + } + b = b->next; + } + } + while (u && !u->ship) { + if (stealthmod > INT_MIN) { + if (u->faction == f || cansee(f, r, u, stealthmod)) { + nr_unit(out, f, u, 4, sr->mode); + } + } + assert(!u->building); + u = u->next; + } + while (sh) { + while (sh && (!u || u->ship != sh)) { + nr_ship(out, sr, sh, f, NULL); + sh = sh->next; + } + if (sh) { + nr_ship(out, sr, sh, f, u); + while (u && u->ship == sh) { + nr_unit(out, f, u, 6, sr->mode); + u = u->next; + } + sh = sh->next; + } + } - assert(!u); + assert(!u); - rnl(F); - rpline(F); - } - if (!is_monsters(f)) { - if (!anyunits) { - rnl(F); - rparagraph(F, LOC(f->locale, "nr_youaredead"), 0, 2, 0); - } - else { - list_address(F, f, ctx->addresses); - } - } - fclose(F); - return 0; + newline(out); + rpline(out); + } + if (!is_monsters(f)) { + if (!anyunits) { + newline(out); + paragraph(out, LOC(f->locale, "nr_youaredead"), 0, 2, 0); + } + else { + list_address(out, f, ctx->addresses); + } + } + fstream_done(&strm); + return 0; } void base36conversion(void) diff --git a/src/report.h b/src/report.h index 5f4da17a9..189a38f0f 100644 --- a/src/report.h +++ b/src/report.h @@ -15,8 +15,10 @@ extern "C" { #endif + struct stream; void register_nr(void); void report_cleanup(void); + void write_spaces(struct stream *out, size_t num); #ifdef __cplusplus } diff --git a/src/reports.c b/src/reports.c index 1d305230f..88b11e31d 100644 --- a/src/reports.c +++ b/src/reports.c @@ -70,6 +70,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "move.h" +#define SCALEWEIGHT 100 /* Faktor, um den die Anzeige von Gewichten skaliert wird */ + bool nocr = false; bool nonr = false; bool noreports = false; @@ -112,8 +114,18 @@ const char *combatstatus[] = { const char *report_kampfstatus(const unit * u, const struct locale *lang) { static char fsbuf[64]; // FIXME: static return value + const char * status = LOC(lang, combatstatus[u->status]); - strlcpy(fsbuf, LOC(lang, combatstatus[u->status]), sizeof(fsbuf)); + if (!status) { + const char *lname = locale_name(lang); + struct locale *wloc = get_or_create_locale(lname); + log_error("no translation for combat status %s in %s", combatstatus[u->status], lname); + locale_setstring(wloc, combatstatus[u->status], combatstatus[u->status]); + strlcpy(fsbuf, combatstatus[u->status], sizeof(fsbuf)); + } + else { + strlcpy(fsbuf, status, sizeof(fsbuf)); + } if (fval(u, UFL_NOAID)) { strcat(fsbuf, ", "); strcat(fsbuf, LOC(lang, "status_noaid")); @@ -124,18 +136,24 @@ const char *report_kampfstatus(const unit * u, const struct locale *lang) const char *hp_status(const unit * u) { - double p = (double)((double)u->hp / (double)(u->number * unit_max_hp(u))); + double p; + int max_hp = u->number * unit_max_hp(u); + + if (u->hp == max_hp) + return NULL; + + p = (double)((double)u->hp / (double)(max_hp)); - if (p > 2.00) - return mkname("damage", "critical"); - if (p > 1.50) - return mkname("damage", "heavily"); if (p < 0.50) return mkname("damage", "badly"); if (p < 0.75) return mkname("damage", "wounded"); if (p < 0.99) return mkname("damage", "exhausted"); + if (p > 2.00) + return mkname("damage", "plusstrong"); + if (p > 1.50) + return mkname("damage", "strong"); return NULL; } @@ -208,19 +226,19 @@ const char **name, const char **basename, int *number, bool singular) static size_t buforder(char *bufp, size_t size, const order * ord, int mode) { size_t tsize = 0; - int bytes; + size_t bytes; - bytes = (int)strlcpy(bufp, ", \"", size); + bytes = strlcpy(bufp, ", \"", size); tsize += bytes; if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); if (mode < ORDERS_IN_NR) { char cmd[ORDERSIZE]; get_command(ord, cmd, sizeof(cmd)); - bytes = (int)strlcpy(bufp, cmd, size); + bytes = strlcpy(bufp, cmd, size); } else { - bytes = (int)strlcpy(bufp, "...", size); + bytes = strlcpy(bufp, "...", size); } tsize += bytes; if (wrptr(&bufp, &size, bytes) != 0) @@ -428,7 +446,7 @@ const faction * viewer) } int -bufunit(const faction * f, const unit * u, int indent, int mode, char *buf, +bufunit(const faction * f, const unit * u, unsigned int indent, int mode, char *buf, size_t size) { int i, dh; @@ -444,15 +462,16 @@ size_t size) char *bufp = buf; bool itemcloak = false; const curse_type *itemcloak_ct = 0; - int bytes; - item result[MAX_INVENTORY]; + int result = 0; + size_t bytes; + item results[MAX_INVENTORY]; itemcloak_ct = ct_find("itemcloak"); if (itemcloak_ct) { itemcloak = curse_active(get_curse(u->attribs, itemcloak_ct)); } - bytes = (int)strlcpy(bufp, unitname(u), size); + bytes = strlcpy(bufp, unitname(u), size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); @@ -463,29 +482,29 @@ size_t size) attrib *a = a_find(u->attribs, &at_group); if (a) { group *g = (group *)a->data.v; - bytes = (int)strlcpy(bufp, ", ", size); + bytes = strlcpy(bufp, ", ", size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); - bytes = (int)strlcpy(bufp, groupid(g, f), size); + bytes = strlcpy(bufp, groupid(g, f), size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } } if (getarnt) { - bytes = (int)strlcpy(bufp, ", ", size); + bytes = strlcpy(bufp, ", ", size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); - bytes = (int)strlcpy(bufp, LOC(f->locale, "anonymous"), size); + bytes = strlcpy(bufp, LOC(f->locale, "anonymous"), size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } else if (a_otherfaction) { faction *otherfaction = get_otherfaction(a_otherfaction); if (otherfaction) { - bytes = (int)strlcpy(bufp, ", ", size); + bytes = strlcpy(bufp, ", ", size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); - bytes = (int)strlcpy(bufp, factionname(otherfaction), size); + bytes = strlcpy(bufp, factionname(otherfaction), size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } @@ -493,27 +512,28 @@ size_t size) } else { if (getarnt) { - bytes = (int)strlcpy(bufp, ", ", size); + bytes = strlcpy(bufp, ", ", size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); - bytes = (int)strlcpy(bufp, LOC(f->locale, "anonymous"), size); + bytes = strlcpy(bufp, LOC(f->locale, "anonymous"), size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } else { if (a_otherfaction && alliedunit(u, f, HELP_FSTEALTH)) { faction *f = get_otherfaction(a_otherfaction); - bytes = - _snprintf(bufp, size, ", %s (%s)", factionname(f), + int result = + (size_t)_snprintf(bufp, size, ", %s (%s)", factionname(f), factionname(u->faction)); - if (bytes < 0 || wrptr(&bufp, &size, bytes) != 0) + bytes = (size_t)result; + if (result < 0 || wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } else { - bytes = (int)strlcpy(bufp, ", ", size); + bytes = strlcpy(bufp, ", ", size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); - bytes = (int)strlcpy(bufp, factionname(fv), size); + bytes = strlcpy(bufp, factionname(fv), size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } @@ -521,30 +541,31 @@ size_t size) } } - bytes = (int)strlcpy(bufp, ", ", size); + bytes = strlcpy(bufp, ", ", size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); if (u->faction != f && a_fshidden && a_fshidden->data.ca[0] == 1 && effskill(u, SK_STEALTH) >= 6) { - bytes = (int)strlcpy(bufp, "? ", size); + bytes = strlcpy(bufp, "? ", size); } else { - bytes = _snprintf(bufp, size, "%d ", u->number); + result = _snprintf(bufp, size, "%d ", u->number); + bytes = (size_t)result; } - if (bytes < 0 || wrptr(&bufp, &size, bytes) != 0) + if (result < 0 || wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); pzTmp = get_racename(u->attribs); if (pzTmp) { - bytes = (int)strlcpy(bufp, pzTmp, size); + bytes = strlcpy(bufp, pzTmp, size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); if (u->faction == f && fval(u_race(u), RCF_SHAPESHIFTANY)) { - bytes = (int)strlcpy(bufp, " (", size); + bytes = strlcpy(bufp, " (", size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); - bytes = (int)strlcpy(bufp, racename(f->locale, u, u_race(u)), size); + bytes = strlcpy(bufp, racename(f->locale, u, u_race(u)), size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); if (size > 1) { @@ -555,14 +576,14 @@ size_t size) } else { const race *irace = u_irace(u); - bytes = (int)strlcpy(bufp, racename(f->locale, u, irace), size); + bytes = strlcpy(bufp, racename(f->locale, u, irace), size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); if (u->faction == f && irace != u_race(u)) { - bytes = (int)strlcpy(bufp, " (", size); + bytes = strlcpy(bufp, " (", size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); - bytes = (int)strlcpy(bufp, racename(f->locale, u, u_race(u)), size); + bytes = strlcpy(bufp, racename(f->locale, u, u_race(u)), size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); if (size > 1) { @@ -573,10 +594,10 @@ size_t size) } if (fval(u, UFL_HERO) && (u->faction == f || omniscient(f))) { - bytes = (int)strlcpy(bufp, ", ", size); + bytes = strlcpy(bufp, ", ", size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); - bytes = (int)strlcpy(bufp, LOC(f->locale, "hero"), size); + bytes = strlcpy(bufp, LOC(f->locale, "hero"), size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } @@ -585,28 +606,28 @@ size_t size) if (u->number && (u->faction == f || telepath_see || isbattle)) { const char *c = hp_status(u); c = c ? LOC(f->locale, c) : 0; - bytes = (int)strlcpy(bufp, ", ", size); + bytes = strlcpy(bufp, ", ", size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); - bytes = (int)strlcpy(bufp, report_kampfstatus(u, f->locale), size); + bytes = strlcpy(bufp, report_kampfstatus(u, f->locale), size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); if (c || fval(u, UFL_HUNGER)) { - bytes = (int)strlcpy(bufp, " (", size); + bytes = strlcpy(bufp, " (", size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); if (c) { - bytes = (int)strlcpy(bufp, c, size); + bytes = strlcpy(bufp, c, size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } if (fval(u, UFL_HUNGER)) { if (c) { - bytes = (int)strlcpy(bufp, ", ", size); + bytes = strlcpy(bufp, ", ", size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } - bytes = (int)strlcpy(bufp, LOC(f->locale, "unit_hungers"), size); + bytes = strlcpy(bufp, LOC(f->locale, "unit_hungers"), size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } @@ -617,19 +638,19 @@ size_t size) } } if (is_guard(u, GUARD_ALL) != 0) { - bytes = (int)strlcpy(bufp, ", ", size); + bytes = strlcpy(bufp, ", ", size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); - bytes = (int)strlcpy(bufp, LOC(f->locale, "unit_guards"), size); + bytes = strlcpy(bufp, LOC(f->locale, "unit_guards"), size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } if ((b = usiege(u)) != NULL) { - bytes = (int)strlcpy(bufp, ", belagert ", size); + bytes = strlcpy(bufp, ", belagert ", size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); - bytes = (int)strlcpy(bufp, buildingname(b), size); + bytes = strlcpy(bufp, buildingname(b), size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } @@ -638,7 +659,7 @@ size_t size) if (u->faction == f || telepath_see) { skill *sv; for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) { - bytes = (int)spskill(bufp, size, f->locale, u, sv, &dh, 1); + bytes = spskill(bufp, size, f->locale, u, sv, &dh, 1); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } @@ -650,10 +671,10 @@ size_t size) } else if (!itemcloak && mode >= see_unit && !(a_fshidden && a_fshidden->data.ca[1] == 1 && effskill(u, SK_STEALTH) >= 3)) { - int n = report_items(u->items, result, MAX_INVENTORY, u, f); + int n = report_items(u->items, results, MAX_INVENTORY, u, f); assert(n >= 0); if (n > 0) - show = result; + show = results; else show = NULL; } @@ -662,27 +683,29 @@ size_t size) } for (itm = show; itm; itm = itm->next) { const char *ic; - int in, bytes; + int in; report_item(u, itm, f, &ic, NULL, &in, false); if (in == 0 || ic == NULL) continue; - bytes = (int)strlcpy(bufp, ", ", size); + bytes = strlcpy(bufp, ", ", size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); if (!dh) { - bytes = _snprintf(bufp, size, "%s: ", LOC(f->locale, "nr_inventory")); - if (bytes < 0 || wrptr(&bufp, &size, bytes) != 0) + result = _snprintf(bufp, size, "%s: ", LOC(f->locale, "nr_inventory")); + bytes = (size_t)result; + if (result < 0 || wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); dh = 1; } if (in == 1) { - bytes = (int)strlcpy(bufp, ic, size); + bytes = strlcpy(bufp, ic, size); } else { - bytes = _snprintf(bufp, size, "%d %s", in, ic); + result = _snprintf(bufp, size, "%d %s", in, ic); + bytes = (size_t)result; } - if (bytes < 0 || wrptr(&bufp, &size, bytes) != 0) + if (result < 0 || wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } @@ -692,26 +715,29 @@ size_t size) if (book) { quicklist *ql = book->spells; int qi, header, maxlevel = effskill(u, SK_MAGIC); - int bytes = _snprintf(bufp, size, ". Aura %d/%d", get_spellpoints(u), max_spellpoints(u->region, u)); - if (bytes < 0 || wrptr(&bufp, &size, bytes) != 0) { + int result = _snprintf(bufp, size, ". Aura %d/%d", get_spellpoints(u), max_spellpoints(u->region, u)); + size_t bytes = (size_t)result; + if (result < 0 || wrptr(&bufp, &size, bytes) != 0) { WARN_STATIC_BUFFER(); } for (header = 0, qi = 0; ql; ql_advance(&ql, &qi, 1)) { spellbook_entry * sbe = (spellbook_entry *)ql_get(ql, qi); if (sbe->level <= maxlevel) { + int result = 0; if (!header) { - bytes = _snprintf(bufp, size, ", %s: ", LOC(f->locale, "nr_spells")); + result = _snprintf(bufp, size, ", %s: ", LOC(f->locale, "nr_spells")); + bytes = (size_t)result; header = 1; } else { - bytes = (int)strlcpy(bufp, ", ", size); + bytes = strlcpy(bufp, ", ", size); } - if (bytes < 0 || wrptr(&bufp, &size, bytes) != 0) { + if (result < 0 || wrptr(&bufp, &size, bytes) != 0) { WARN_STATIC_BUFFER(); } - bytes = (int)strlcpy(bufp, spell_name(sbe->sp, f->locale), size); - if (bytes < 0 || wrptr(&bufp, &size, bytes) != 0) { + bytes = strlcpy(bufp, spell_name(sbe->sp, f->locale), size); + if (wrptr(&bufp, &size, bytes) != 0) { WARN_STATIC_BUFFER(); } } @@ -722,9 +748,10 @@ size_t size) break; } if (i != MAXCOMBATSPELLS) { - bytes = + int result = _snprintf(bufp, size, ", %s: ", LOC(f->locale, "nr_combatspells")); - if (bytes < 0 || wrptr(&bufp, &size, bytes) != 0) + size_t bytes = (size_t)result; + if (result < 0 || wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); dh = 0; @@ -734,7 +761,7 @@ size_t size) dh = 1; } else { - bytes = (int)strlcpy(bufp, ", ", size); + bytes = strlcpy(bufp, ", ", size); if (bytes && wrptr(&bufp, &size, bytes) != 0) { WARN_STATIC_BUFFER(); } @@ -742,20 +769,20 @@ size_t size) sp = get_combatspell(u, i); if (sp) { int sl = get_combatspelllevel(u, i); - bytes = - (int)strlcpy(bufp, spell_name(sp, u->faction->locale), size); + bytes = strlcpy(bufp, spell_name(sp, u->faction->locale), size); if (bytes && wrptr(&bufp, &size, bytes) != 0) { WARN_STATIC_BUFFER(); } if (sl > 0) { - bytes = _snprintf(bufp, size, " (%d)", sl); - if (bytes < 0 || wrptr(&bufp, &size, bytes) != 0) + result = _snprintf(bufp, size, " (%d)", sl); + bytes = (size_t)result; + if (result < 0 || wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } } else { - bytes = (int)strlcpy(bufp, LOC(f->locale, "nr_nospells"), size); + bytes = strlcpy(bufp, LOC(f->locale, "nr_nospells"), size); if (bytes && wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } @@ -766,9 +793,10 @@ size_t size) bool printed = 0; order *ord;; for (ord = u->old_orders; ord; ord = ord->next) { - if (is_repeated(ord)) { + keyword_t kwd = getkeyword(ord); + if (is_repeated(kwd)) { if (printed < ORDERS_IN_NR) { - bytes = (int)buforder(bufp, size, ord, printed++); + bytes = buforder(bufp, size, ord, printed++); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } @@ -778,9 +806,10 @@ size_t size) } if (printed < ORDERS_IN_NR) for (ord = u->orders; ord; ord = ord->next) { - if (is_repeated(ord)) { + keyword_t kwd = getkeyword(ord); + if (is_repeated(kwd)) { if (printed < ORDERS_IN_NR) { - bytes = (int)buforder(bufp, size, ord, printed++); + bytes = buforder(bufp, size, ord, printed++); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } @@ -794,11 +823,11 @@ size_t size) str = u_description(u, f->locale); if (str) { - bytes = (int)strlcpy(bufp, "; ", size); + bytes = strlcpy(bufp, "; ", size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); - bytes = (int)strlcpy(bufp, str, size); + bytes = strlcpy(bufp, str, size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); @@ -812,13 +841,13 @@ size_t size) } pzTmp = uprivate(u); if (u->faction == f && pzTmp) { - bytes = (int)strlcpy(bufp, " (Bem: ", size); + bytes = strlcpy(bufp, " (Bem: ", size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); - bytes = (int)strlcpy(bufp, pzTmp, size); + bytes = strlcpy(bufp, pzTmp, size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); - bytes = (int)strlcpy(bufp, ")", size); + bytes = strlcpy(bufp, ")", size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } @@ -846,7 +875,7 @@ const struct unit * u, struct skill * sv, int *dh, int days) { char *bufp = buffer; int i, effsk; - int bytes; + size_t bytes; size_t tsize = 0; if (!u->number) @@ -857,30 +886,30 @@ const struct unit * u, struct skill * sv, int *dh, int days) } } - bytes = (int)strlcpy(bufp, ", ", size); + bytes = strlcpy(bufp, ", ", size); tsize += bytes; if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); if (!*dh) { - bytes = (int)strlcpy(bufp, LOC(lang, "nr_skills"), size); + bytes = strlcpy(bufp, LOC(lang, "nr_skills"), size); tsize += bytes; if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); - bytes = (int)strlcpy(bufp, ": ", size); + bytes = strlcpy(bufp, ": ", size); tsize += bytes; if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); *dh = 1; } - bytes = (int)strlcpy(bufp, skillname(sv->id, lang), size); + bytes = strlcpy(bufp, skillname(sv->id, lang), size); tsize += bytes; if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); - bytes = (int)strlcpy(bufp, " ", size); + bytes = strlcpy(bufp, " ", size); tsize += bytes; if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); @@ -889,13 +918,13 @@ const struct unit * u, struct skill * sv, int *dh, int days) sc_mage *mage = get_mage(u); if (mage && mage->magietyp != M_GRAY) { bytes = - (int)strlcpy(bufp, LOC(lang, mkname("school", + strlcpy(bufp, LOC(lang, mkname("school", magic_school[mage->magietyp])), size); tsize += bytes; if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); - bytes = (int)strlcpy(bufp, " ", size); + bytes = strlcpy(bufp, " ", size); tsize += bytes; if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); @@ -939,9 +968,60 @@ const struct unit * u, struct skill * sv, int *dh, int days) return tsize; } -void lparagraph(struct strlist **SP, char *s, int indent, char mark) +void split_paragraph(strlist ** SP, const char *s, unsigned int indent, unsigned int width, char mark) { + /* Die Liste SP wird mit dem String s aufgefuellt, mit indent und einer + * mark, falls angegeben. SP wurde also auf 0 gesetzt vor dem Aufruf. + * Vgl. spunit (). */ + bool firstline; + static char buf[REPORTWIDTH + 1]; // FIXME: static buffer, artificial limit + size_t len = strlen(s); + + assert(width <= REPORTWIDTH); + width -= indent; + firstline = (mark != 0 && indent > 2); + *SP = 0; + + while (len > 0) { + unsigned int j; + const char *cut = 0, *space = strchr(s, ' '); + while (space && *space && (space - s) <= (ptrdiff_t)width) { + cut = space; + space = strchr(space + 1, ' '); + if (!space && len < width) { + cut = space = s + len; + } + } + + for (j = 0; j != indent; j++) + buf[j] = ' '; + + if (firstline) { + buf[indent - 2] = mark; + firstline = false; + } + if (!cut) { + cut = s + _min(len, REPORTWIDTH); + } + strncpy(buf + indent, s, cut - s); + buf[indent + (cut - s)] = 0; + addstrlist(SP, buf); // TODO: too much string copying, cut out this function + while (*cut == ' ') { + ++cut; + } + len -= (cut - s); + s = cut; + } +} + +void sparagraph(strlist ** SP, const char *s, unsigned int indent, char mark) +{ + split_paragraph(SP, s, indent, REPORTWIDTH, mark); +} + +void lparagraph(struct strlist **SP, char *s, unsigned int indent, char mark) +{ /* Die Liste SP wird mit dem String s aufgefuellt, mit indent und einer * mark, falls angegeben. SP wurde also auf 0 gesetzt vor dem Aufruf. * Vgl. spunit (). */ @@ -959,7 +1039,7 @@ void lparagraph(struct strlist **SP, char *s, int indent, char mark) } void -spunit(struct strlist **SP, const struct faction *f, const unit * u, int indent, +spunit(struct strlist **SP, const struct faction *f, const unit * u, unsigned int indent, int mode) { char buf[DISPLAYSIZE]; @@ -1697,7 +1777,7 @@ static seen_region **prepare_report(faction * f) int write_reports(faction * f, time_t ltime) { - int backup = 1, maxbackup = 128 * 1000; + unsigned int backup = 1, maxbackup = 128 * 1000; bool gotit = false; struct report_context ctx; const char *encoding = "UTF-8"; @@ -1756,39 +1836,6 @@ int write_reports(faction * f, time_t ltime) return 0; } -static void nmr_warnings(void) -{ - faction *f, *fa; -#define FRIEND (HELP_GUARD|HELP_MONEY) - for (f = factions; f; f = f->next) { - if (!fval(f, FFL_NOIDLEOUT) && (turn - f->lastorders) >= 2) { - message *msg = NULL; - for (fa = factions; fa; fa = fa->next) { - int warn = 0; - if (get_param_int(global.parameters, "rules.alliances", 0) != 0) { - if (f->alliance && f->alliance == fa->alliance) { - warn = 1; - } - } - else if (alliedfaction(NULL, f, fa, FRIEND) - && alliedfaction(NULL, fa, f, FRIEND)) { - warn = 1; - } - if (warn) { - if (msg == NULL) { - msg = - msg_message("warn_dropout", "faction turns", f, - turn - f->lastorders); - } - add_message(&fa->msgs, msg); - } - } - if (msg != NULL) - msg_release(msg); - } - } -} - static void report_donations(void) { region *r; @@ -1833,8 +1880,14 @@ static void write_script(FILE * F, const faction * f) fputc('\n', F); } +static void check_messages_exist(void) { + ct_checknames(); +} + int init_reports(void) { + check_messages_exist(); + prepare_reports(); { if (_access(reportpath(), 0) != 0) { @@ -1861,7 +1914,6 @@ int reports(void) if (verbosity >= 1) { log_printf(stdout, "Writing reports for turn %d:", turn); } - nmr_warnings(); report_donations(); remove_empty_units(); @@ -1978,7 +2030,7 @@ f_regionid(const region * r, const faction * f, char *buffer, size_t size) int nx = r->x, ny = r->y; int named = (name && name[0]); pnormalize(&nx, &ny, pl); - adjust_coordinates(f, &nx, &ny, pl, r); + adjust_coordinates(f, &nx, &ny, pl); len = strlcpy(buffer, rname(r, f ? f->locale : 0), size); _snprintf(buffer + len, size - len, " (%d,%d%s%s)", nx, ny, named ? "," : "", (named) ? name : ""); buffer[size - 1] = 0; @@ -2050,6 +2102,7 @@ static void eval_spell(struct opstack **stack, const void *userdata) const struct spell *sp = (const struct spell *)opop(stack).v; const char *c = sp ? spell_name(sp, f->locale) : LOC(f->locale, "an_unknown_spell"); + assert(c || !"spell without description!"); size_t len = strlen(c); variant var; @@ -2063,6 +2116,7 @@ static void eval_curse(struct opstack **stack, const void *userdata) const struct curse_type *sp = (const struct curse_type *)opop(stack).v; const char *c = sp ? curse_name(sp, f->locale) : LOC(f->locale, "an_unknown_curse"); + assert(c || !"spell effect without description!"); size_t len = strlen(c); variant var; @@ -2074,7 +2128,7 @@ static void eval_unitname(struct opstack **stack, const void *userdata) { /* unit -> string */ const struct faction *f = (const struct faction *)userdata; const struct unit *u = (const struct unit *)opop(stack).v; - const char *c = u ? u->name : LOC(f->locale, "an_unknown_unit"); + const char *c = u ? unit_getname(u) : LOC(f->locale, "an_unknown_unit"); size_t len = strlen(c); variant var; @@ -2086,7 +2140,7 @@ static void eval_unitid(struct opstack **stack, const void *userdata) { /* unit -> int */ const struct faction *f = (const struct faction *)userdata; const struct unit *u = (const struct unit *)opop(stack).v; - const char *c = u ? u->name : LOC(f->locale, "an_unknown_unit"); + const char *c = u ? unit_getname(u) : LOC(f->locale, "an_unknown_unit"); size_t len = strlen(c); variant var; @@ -2263,8 +2317,9 @@ static void eval_resources(struct opstack **stack, const void *userdata) while (res != NULL && size > 4) { const char *rname = resourcename(res->type, (res->number != 1) ? NMF_PLURAL : 0); - int bytes = _snprintf(bufp, size, "%d %s", res->number, LOC(lang, rname)); - if (bytes < 0 || wrptr(&bufp, &size, bytes) != 0 || size < sizeof(buf) / 2) { + int result = _snprintf(bufp, size, "%d %s", res->number, LOC(lang, rname)); + size_t bytes = (size_t)result; + if (result < 0 || wrptr(&bufp, &size, bytes) != 0 || size < sizeof(buf) / 2) { WARN_STATIC_BUFFER(); break; } @@ -2277,7 +2332,7 @@ static void eval_resources(struct opstack **stack, const void *userdata) } } *bufp = 0; - var.v = strcpy(balloc(bufp - buf + 1), buf); + var.v = strcpy(balloc((size_t)(bufp - buf + 1)), buf); opush(stack, var); } @@ -2303,7 +2358,7 @@ static void eval_regions(struct opstack **stack, const void *userdata) } for (i = begin; i < end; ++i) { const char *rname = (const char *)regionname(regions->regions[i], report); - int bytes = (int)strlcpy(bufp, rname, size); + size_t bytes = strlcpy(bufp, rname, size); if (bytes && wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); @@ -2314,7 +2369,7 @@ static void eval_regions(struct opstack **stack, const void *userdata) } } *bufp = 0; - var.v = strcpy(balloc(bufp - buf + 1), buf); + var.v = strcpy(balloc((size_t)(bufp - buf + 1)), buf); opush(stack, var); } @@ -2339,15 +2394,16 @@ static void eval_trail(struct opstack **stack, const void *userdata) region *r = regions->regions[i]; const char *trail = trailinto(r, lang); const char *rn = f_regionid_s(r, report); - int bytes = _snprintf(bufp, size, trail, rn); - if (bytes < 0 || wrptr(&bufp, &size, bytes) != 0) + int result = _snprintf(bufp, size, trail, rn); + size_t bytes = (size_t)result; + if (result < 0 || wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); if (i + 2 < end) { - bytes = (int)strlcpy(bufp, ", ", size); + bytes = strlcpy(bufp, ", ", size); } else if (i + 1 < end) { - bytes = (int)strlcpy(bufp, LOC(lang, "list_and"), size); + bytes = strlcpy(bufp, LOC(lang, "list_and"), size); } else bytes = 0; @@ -2357,7 +2413,7 @@ static void eval_trail(struct opstack **stack, const void *userdata) } } *bufp = 0; - var.v = strcpy(balloc(bufp - buf + 1), buf); + var.v = strcpy(balloc((size_t)(bufp - buf + 1)), buf); opush(stack, var); #ifdef _SECURECRT_ERRCODE_VALUES_DEFINED if (errno == ERANGE) { diff --git a/src/reports.h b/src/reports.h index cbca88866..93b3ab122 100644 --- a/src/reports.h +++ b/src/reports.h @@ -1,3 +1,4 @@ +#pragma once /* Copyright (c) 1998-2015, Enno Rehling Katja Zedel #include #include #include @@ -45,12 +47,12 @@ extern "C" { struct unit *can_find(struct faction *, struct faction *); /* funktionen zum schreiben eines reports */ - void sparagraph(struct strlist **SP, const char *s, int indent, char mark); - void lparagraph(struct strlist **SP, char *s, int indent, char mark); + void sparagraph(struct strlist **SP, const char *s, unsigned int indent, char mark); + void lparagraph(struct strlist **SP, char *s, unsigned int indent, char mark); const char *hp_status(const struct unit *u); size_t spskill(char *pbuf, size_t siz, const struct locale *lang, const struct unit *u, struct skill *sv, int *dh, int days); /* mapper */ void spunit(struct strlist **SP, const struct faction *f, - const struct unit *u, int indent, int mode); + const struct unit *u, unsigned int indent, int mode); int reports(void); int write_reports(struct faction *f, time_t ltime); @@ -103,7 +105,7 @@ extern "C" { void register_reporttype(const char *extension, report_fun write, int flag); - int bufunit(const struct faction *f, const struct unit *u, int indent, + int bufunit(const struct faction *f, const struct unit *u, unsigned int indent, int mode, char *buf, size_t size); const char *trailinto(const struct region *r, @@ -149,6 +151,7 @@ extern "C" { void addstrlist(strlist ** SP, const char *s); void freestrlist(strlist * s); + void split_paragraph(strlist ** SP, const char *s, unsigned int indent, unsigned int width, char mark); #define GR_PLURAL 0x01 /* grammar: plural */ diff --git a/src/reports.test.c b/src/reports.test.c index 3d9536ee1..9dd9f0913 100644 --- a/src/reports.test.c +++ b/src/reports.test.c @@ -1,6 +1,7 @@ #include #include #include "reports.h" +#include "report.h" #include #include @@ -10,6 +11,8 @@ #include #include +#include +#include #include #include @@ -71,12 +74,12 @@ static void test_regionid(CuTest * tc) { memset(buffer, 0x7d, sizeof(buffer)); len = f_regionid(r, 0, buffer, sizeof(buffer)); - CuAssertIntEquals(tc, 11, len); + CuAssertIntEquals(tc, 11, (int)len); CuAssertStrEquals(tc, "plain (0,0)", buffer); memset(buffer, 0x7d, sizeof(buffer)); len = f_regionid(r, 0, buffer, 11); - CuAssertIntEquals(tc, 10, len); + CuAssertIntEquals(tc, 10, (int)len); CuAssertStrEquals(tc, "plain (0,0", buffer); CuAssertIntEquals(tc, 0x7d, buffer[11]); } @@ -98,11 +101,68 @@ static void test_seen_faction(CuTest *tc) { CuAssertTrue(tc, f1->no < f2->no); } +static void test_write_spaces(CuTest *tc) { + stream out = { 0 }; + char buf[1024]; + size_t len; + + mstream_init(&out); + write_spaces(&out, 4); + out.api->rewind(out.handle); + len = out.api->read(out.handle, buf, sizeof(buf)); + buf[len] = '\0'; + CuAssertStrEquals(tc, " ", buf); + CuAssertIntEquals(tc, ' ', buf[3]); + mstream_done(&out); +} + +static void test_write_many_spaces(CuTest *tc) { + stream out = { 0 }; + char buf[1024]; + size_t len; + + mstream_init(&out); + write_spaces(&out, 100); + out.api->rewind(out.handle); + len = out.api->read(out.handle, buf, sizeof(buf)); + buf[len] = '\0'; + CuAssertIntEquals(tc, 100, (int)len); + CuAssertIntEquals(tc, ' ', buf[99]); + mstream_done(&out); +} + +static void test_sparagraph(CuTest *tc) { + strlist *sp = 0; + split_paragraph(&sp, "Hello World", 0, 16, 0); + CuAssertPtrNotNull(tc, sp); + CuAssertStrEquals(tc, "Hello World", sp->s); + CuAssertPtrEquals(tc, 0, sp->next); + split_paragraph(&sp, "Hello World", 4, 16, 0); + CuAssertPtrNotNull(tc, sp); + CuAssertStrEquals(tc, " Hello World", sp->s); + CuAssertPtrEquals(tc, 0, sp->next); + split_paragraph(&sp, "Hello World", 4, 16, '*'); + CuAssertPtrNotNull(tc, sp); + CuAssertStrEquals(tc, " * Hello World", sp->s); + CuAssertPtrEquals(tc, 0, sp->next); + split_paragraph(&sp, "12345678 90 12345678", 0, 8, '*'); + CuAssertPtrNotNull(tc, sp); + CuAssertStrEquals(tc, "12345678", sp->s); + CuAssertPtrNotNull(tc, sp->next); + CuAssertStrEquals(tc, "90", sp->next->s); + CuAssertPtrNotNull(tc, sp->next->next); + CuAssertStrEquals(tc, "12345678", sp->next->next->s); + CuAssertPtrEquals(tc, 0, sp->next->next->next); +} + CuSuite *get_reports_suite(void) { CuSuite *suite = CuSuiteNew(); SUITE_ADD_TEST(suite, test_reorder_units); SUITE_ADD_TEST(suite, test_seen_faction); SUITE_ADD_TEST(suite, test_regionid); + SUITE_ADD_TEST(suite, test_write_spaces); + SUITE_ADD_TEST(suite, test_write_many_spaces); + SUITE_ADD_TEST(suite, test_sparagraph); return suite; } diff --git a/src/skill.c b/src/skill.c index 7b4551683..3bee18005 100644 --- a/src/skill.c +++ b/src/skill.c @@ -97,7 +97,7 @@ skill_t get_skill(const char *s, const struct locale * lang) char * str = transliterate(buffer, sizeof(buffer) - sizeof(int), s); if (str) { int i; - const void * match; + void * match; void **tokens = get_translations(lang, UT_SKILLS); struct critbit_tree *cb = (critbit_tree *)*tokens; if (cb && cb_find_prefix(cb, str, strlen(str), &match, 1, 0)) { diff --git a/src/spells.c b/src/spells.c index 82aca3720..ed6898139 100644 --- a/src/spells.c +++ b/src/spells.c @@ -102,7 +102,7 @@ #include /* ----------------------------------------------------------------------- */ -static float zero_effect = 0.0F; +static double zero_effect = 0.0; attrib_type at_wdwpyramid = { "wdwpyramid", NULL, NULL, NULL, a_writevoid, a_readvoid @@ -298,7 +298,7 @@ static void magicanalyse_ship(ship * sh, unit * mage, double force) } -static int break_curse(attrib ** alist, int cast_level, float force, curse * c) +static int break_curse(attrib ** alist, int cast_level, double force, curse * c) { int succ = 0; /* attrib **a = a_find(*ap, &at_curse); */ @@ -327,7 +327,7 @@ static int break_curse(attrib ** alist, int cast_level, float force, curse * c) * auf alle Verzauberungen wirken. Ansonsten pruefe, ob der Curse vom * richtigen Typ ist. */ if (!c || c == c1) { - float remain = destr_curse(c1, cast_level, force); + double remain = destr_curse(c1, cast_level, force); if (remain < force) { succ = cast_level; force = remain; @@ -480,6 +480,7 @@ static const race *select_familiar(const race * magerace, magic_t magiegebiet) assert(magerace->familiars[0]); if (rnd >= 70) { retval = magerace->familiars[magiegebiet]; + assert(retval); } else { retval = magerace->familiars[0]; @@ -490,7 +491,7 @@ static const race *select_familiar(const race * magerace, magic_t magiegebiet) unsigned int maxlen = listlen(familiarraces); if (maxlen > 0) { race_list *rclist = familiarraces; - int index = rng_int() % maxlen; + unsigned int index = rng_uint() % maxlen; while (index-- > 0) { rclist = rclist->next; } @@ -536,7 +537,8 @@ static int sp_summon_familiar(castorder * co) int cast_level = co->level; const race *rc; int sk; - int dh, dh1, bytes; + int dh, dh1; + size_t bytes; message *msg; char zText[2048], *bufp = zText; size_t size = sizeof(zText) - 1; @@ -545,7 +547,7 @@ static int sp_summon_familiar(castorder * co) cmistake(mage, co->order, 199, MSG_MAGIC); return 0; } - rc = select_familiar(mage->faction->race, mage->faction->magiegebiet); + rc = select_familiar(mage->_race, mage->faction->magiegebiet); if (rc == NULL) { log_error("could not find suitable familiar for %s.\n", mage->faction->race->_name); return 0; @@ -597,17 +599,17 @@ static int sp_summon_familiar(castorder * co) else { if (dh == 0) { bytes = - (int)strlcpy(bufp, (const char *)LOC(mage->faction->locale, + strlcpy(bufp, (const char *)LOC(mage->faction->locale, "list_and"), size); } else { - bytes = (int)strlcpy(bufp, (const char *)", ", size); + bytes = strlcpy(bufp, (const char *)", ", size); } if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } bytes = - (int)strlcpy(bufp, (const char *)skillname((skill_t)sk, mage->faction->locale), + strlcpy(bufp, (const char *)skillname((skill_t)sk, mage->faction->locale), size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); @@ -635,7 +637,7 @@ static int sp_destroy_magic(castorder * co) { unit *mage = co->magician.u; int cast_level = co->level; - float force = co->force; + double force = co->force; spellparameter *pa = co->par; curse *c = NULL; char ts[80]; @@ -800,7 +802,7 @@ static int sp_goodwinds(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float power = co->force; + double power = co->force; int duration = cast_level + 1; spellparameter *pa = co->par; message *m; @@ -897,7 +899,7 @@ static int sp_summonent(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float power = co->force; + double power = co->force; unit *u; attrib *a; int ents; @@ -908,7 +910,7 @@ static int sp_summonent(castorder * co) return 0; } - ents = (int)_min(power * power, rtrees(r, 2)); + ents = _min((int)(power * power), rtrees(r, 2)); u = create_unit(r, mage->faction, ents, get_race(RC_TREEMAN), 0, NULL, mage); @@ -1123,7 +1125,7 @@ static int sp_hain(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float force = co->force; + double force = co->force; if (!r->land) { cmistake(mage, co->order, 296, MSG_MAGIC); @@ -1169,7 +1171,7 @@ static int sp_mallornhain(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float force = co->force; + double force = co->force; if (!r->land) { cmistake(mage, co->order, 296, MSG_MAGIC); @@ -1203,7 +1205,7 @@ static void fumble_ents(const castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; /* int cast_level = co->level; */ - float force = co->force; + double force = co->force; if (!r->land) { cmistake(mage, co->order, 296, MSG_MAGIC); @@ -1299,16 +1301,17 @@ static int sp_rosthauch(castorder * co) for (; iweapon != NULL; iweapon = iweapon->next) { item **ip = i_find(&u->items, iweapon->type); if (*ip) { - int i = _min((*ip)->number, force); + float chance = (float)_min((*ip)->number, force); if (iweapon->chance < 1.0) { - i = (int)(i * iweapon->chance); + chance *= iweapon->chance; } - if (i > 0) { - force -= i; - ironweapon += i; - i_change(ip, iweapon->type, -i); + if (chance > 0) { + int ichange = (int)chance; + force -= ichange; + ironweapon += ichange; + i_change(ip, iweapon->type, -ichange); if (iweapon->rusty) { - i_change(&u->items, iweapon->rusty, i); + i_change(&u->items, iweapon->rusty, ichange); } } } @@ -1366,10 +1369,10 @@ static int sp_kaelteschutz(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float force = co->force; + double force = co->force; int duration = _max(cast_level, (int)force) + 1; spellparameter *pa = co->par; - float effect; + double effect; force *= 10; /* 10 Personen pro Force-Punkt */ @@ -1429,7 +1432,7 @@ static int sp_sparkle(castorder * co) int cast_level = co->level; spellparameter *pa = co->par; int duration = cast_level + 1; - float effect; + double effect; /* wenn kein Ziel gefunden, Zauber abbrechen */ if (pa->param[0]->flag == TARGET_NOTFOUND) @@ -1489,7 +1492,7 @@ static int sp_create_irongolem(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float force = co->force; + double force = co->force; int number = lovar(force * 8 * RESOURCE_QUANTITY); if (number < 1) number = 1; @@ -1614,9 +1617,9 @@ static int sp_great_drought(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float force = co->force; + double force = co->force; int duration = 2; - float effect; + double effect; if (fval(r->terrain, SEA_REGION)) { cmistake(mage, co->order, 189, MSG_MAGIC); @@ -1741,7 +1744,7 @@ static int sp_treewalkenter(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; spellparameter *pa = co->par; - float power = co->force; + double power = co->force; int cast_level = co->level; region *rt; int remaining_cap; @@ -1866,7 +1869,7 @@ static int sp_treewalkexit(castorder * co) int erfolg = 0; region *r = co_get_region(co); unit *mage = co->magician.u; - float power = co->force; + double power = co->force; spellparameter *pa = co->par; int cast_level = co->level; @@ -2005,7 +2008,7 @@ static int sp_holyground(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float power = co->force; + double power = co->force; message *msg = msg_message("sp_holyground_effect", "mage region", mage, r); report_spell(mage, r, msg); msg_release(msg); @@ -2040,8 +2043,8 @@ static int sp_homestone(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float force = co->force; - float effect; + double force = co->force; + double effect; message *msg; if (!mage->building || mage->building->type != bt_find("castle")) { cmistake(mage, co->order, 197, MSG_MAGIC); @@ -2099,7 +2102,7 @@ static int sp_drought(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float power = co->force; + double power = co->force; int duration = (int)power + 1; message *msg; @@ -2124,7 +2127,7 @@ static int sp_drought(castorder * co) c->duration = _max(c->duration, (int)power); } else { - float effect = 4.0; + double effect = 4.0; /* Baeume und Pferde sterben */ rsettrees(r, 2, rtrees(r, 2) / 2); rsettrees(r, 1, rtrees(r, 1) / 2); @@ -2220,7 +2223,7 @@ static int sp_stormwinds(castorder * co) int erfolg = 0; region *r = co_get_region(co); unit *mage = co->magician.u; - float power = co->force; + double power = co->force; spellparameter *pa = co->par; int n, force = (int)power; message *m = NULL; @@ -2500,8 +2503,8 @@ static int sp_fumblecurse(castorder * co) int duration; unit *mage = co->magician.u; int cast_level = co->level; - float force = co->force; - float effect; + double force = co->force; + double effect; curse *c; spellparameter *pa = co->par; @@ -2533,9 +2536,9 @@ void patzer_fumblecurse(const castorder * co) { unit *mage = co->magician.u; int cast_level = co->level; - float force = co->force; + double force = co->force; int duration = (cast_level / 2) + 1; - float effect; + double effect; curse *c; effect = force / 2; @@ -2572,7 +2575,7 @@ static int sp_summondragon(castorder * co) unit *mage = co->magician.u; unit *u; int cast_level = co->level; - float power = co->force; + double power = co->force; region_list *rl, *rl2; faction *f; int time; @@ -2644,7 +2647,7 @@ static int sp_firewall(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float force = co->force; + double force = co->force; spellparameter *pa = co->par; direction_t dir; region *r2; @@ -2817,9 +2820,9 @@ static int dc_age(struct curse *c) if (curse_active(c)) while (*up != NULL) { unit *u = *up; + int hp; double damage = c->effect * u->number; - freset(u->faction, FFL_SELECT); if (u->number <= 0 || target_resists_magic(mage, u, TYP_UNIT, 0)) { up = &u->next; continue; @@ -2827,8 +2830,9 @@ static int dc_age(struct curse *c) /* Reduziert durch Magieresistenz */ damage *= (1.0 - magic_resistance(u)); - change_hitpoints(u, -(int)damage); + hp = change_hitpoints(u, -(int)damage); + ADDMSG(&u->faction->msgs, msg_message((hp>0)?"poison_damage":"poison_death", "region unit", r, u)); if (*up == u) up = &u->next; } @@ -2841,9 +2845,9 @@ static struct curse_type ct_deathcloud = { NULL, dc_age }; -static curse *mk_deathcloud(unit * mage, region * r, float force, int duration) +static curse *mk_deathcloud(unit * mage, region * r, double force, int duration) { - float effect; + double effect; curse *c; effect = force / 2; @@ -2876,7 +2880,7 @@ static int dc_read_compat(struct attrib *a, void *target, struct storage * store r = findregion(rx, ry); if (r != NULL) { - float effect; + double effect; curse *c; effect = strength; @@ -3022,7 +3026,7 @@ static int sp_summonshadow(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float force = co->force; + double force = co->force; unit *u; int val, number = (int)(force * force); @@ -3063,7 +3067,7 @@ static int sp_summonshadowlords(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float force = co->force; + double force = co->force; int amount = (int)(force * force); u = create_unit(r, mage->faction, amount, get_race(RC_SHADOWLORD), 0, @@ -3190,8 +3194,8 @@ static int sp_magicboost(castorder * co) curse *c; unit *mage = co->magician.u; int cast_level = co->level; - float power = co->force; - float effect; + double power = co->force; + double effect; trigger *tsummon; static const curse_type *ct_auraboost; static const curse_type *ct_magicboost; @@ -3423,7 +3427,7 @@ static int sp_analysesong_obj(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float force = co->force; + double force = co->force; spellparameter *pa = co->par; obj = pa->param[0]->typ; @@ -3472,7 +3476,7 @@ static int sp_analysesong_unit(castorder * co) unit *u; unit *mage = co->magician.u; int cast_level = co->level; - float force = co->force; + double force = co->force; spellparameter *pa = co->par; /* wenn kein Ziel gefunden, Zauber abbrechen */ @@ -3557,7 +3561,7 @@ static int sp_charmingsong(castorder * co) skill_t i; unit *mage = co->magician.u; int cast_level = co->level; - float force = co->force; + double force = co->force; spellparameter *pa = co->par; int resist_bonus = 0; int tb = 0; @@ -3646,7 +3650,7 @@ static int sp_song_resistmagic(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float force = co->force; + double force = co->force; int duration = (int)force + 1; create_curse(mage, &r->attribs, ct_find("goodmagicresistancezone"), @@ -3675,7 +3679,7 @@ static int sp_song_susceptmagic(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float force = co->force; + double force = co->force; int duration = (int)force + 1; create_curse(mage, &r->attribs, ct_find("badmagicresistancezone"), @@ -3757,7 +3761,7 @@ static int sp_raisepeasantmob(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float force = co->force; + double force = co->force; int duration = (int)force + 1; faction *monsters = get_monsters(); message *msg; @@ -3881,7 +3885,7 @@ static int sp_song_of_peace(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float force = co->force; + double force = co->force; int duration = 2 + lovar(force / 2); message *msg[2] = { NULL, NULL }; @@ -3930,9 +3934,9 @@ static int sp_generous(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float force = co->force; + double force = co->force; int duration = (int)force + 1; - float effect; + double effect; message *msg[2] = { NULL, NULL }; if (is_cursed(r->attribs, C_DEPRESSION, 0)) { @@ -3988,7 +3992,7 @@ static int sp_recruit(castorder * co) double n; unit *mage = co->magician.u; int cast_level = co->level; - float force = co->force; + double force = co->force; faction *f = mage->faction; const struct race *rc = f->race; @@ -4004,7 +4008,7 @@ static int sp_recruit(castorder * co) * Bauer, nur die Kosten steigen. */ n = (pow(force, 1.6) * 100) / f->race->recruitcost; if (rc->recruit_multi != 0) { - double multp = maxp / rc->recruit_multi; + double multp = (double)maxp / rc->recruit_multi; n = _min(multp, n); n = _max(n, 1); rsetpeasants(r, maxp - (int)(n * rc->recruit_multi)); @@ -4043,7 +4047,7 @@ static int sp_bigrecruit(castorder * co) int n, maxp = rpeasants(r); unit *mage = co->magician.u; int cast_level = co->level; - float force = co->force; + double force = co->force; faction *f = mage->faction; message *msg; @@ -4054,7 +4058,7 @@ static int sp_bigrecruit(castorder * co) /* Fuer vergleichbare Erfolge bei unterschiedlichen Rassen die * Rekrutierungskosten mit einfliessen lassen. */ - n = (int)force + lovar((force * force * 1000) / f->race->recruitcost); + n = (int)force + lovar((force * force * 1000) / (float)f->race->recruitcost); if (f->race == get_race(RC_ORC)) { n = _min(2 * maxp, n); n = _max(n, 1); @@ -4166,7 +4170,7 @@ static int sp_seduce(castorder * co) unit *mage = co->magician.u; spellparameter *pa = co->par; int cast_level = co->level; - float force = co->force; + double force = co->force; /* wenn kein Ziel gefunden, Zauber abbrechen */ if (pa->param[0]->flag == TARGET_NOTFOUND) @@ -4197,7 +4201,7 @@ static int sp_seduce(castorder * co) loot += rng_int() % 2; } if (loot > 0) { - loot = (int)_min(loot, force * 5); + loot = _min(loot, (int)(force * 5)); } } if (loot > 0) { @@ -4242,8 +4246,8 @@ static int sp_calm_monster(castorder * co) unit *mage = co->magician.u; spellparameter *pa = co->par; int cast_level = co->level; - float force = co->force; - float effect; + double force = co->force; + double effect; message *msg; /* wenn kein Ziel gefunden, Zauber abbrechen */ @@ -4258,7 +4262,7 @@ static int sp_calm_monster(castorder * co) return 0; } - effect = (float)mage->faction->subscription; + effect = mage->faction->subscription; c = create_curse(mage, &target->attribs, ct_find("calmmonster"), force, (int)force, effect, 0); if (c == NULL) { @@ -4314,7 +4318,7 @@ static int sp_headache(castorder * co) } if (smax != NULL) { /* wirkt auf maximal 10 Personen */ - int change = _min(10, target->number) * (rng_int() % 2 + 1) / target->number; + unsigned int change = _min(10, target->number) * (rng_uint() % 2 + 1) / target->number; reduce_skill(target, smax, change); } set_order(&target->thisorder, NULL); @@ -4350,7 +4354,7 @@ static int sp_raisepeasants(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float power = co->force; + double power = co->force; message *msg; if (rpeasants(r) == 0) { @@ -4358,7 +4362,7 @@ static int sp_raisepeasants(castorder * co) "error_nopeasants", "")); return 0; } - bauern = (int)_min(rpeasants(r), power * 250); + bauern = _min(rpeasants(r), (int)(power * 250)); rsetpeasants(r, rpeasants(r) - bauern); u2 = @@ -4403,7 +4407,7 @@ static int sp_depression(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float force = co->force; + double force = co->force; int duration = (int)force + 1; message *msg; @@ -4470,7 +4474,7 @@ int sp_icastle(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float power = co->force; + double power = co->force; spellparameter *pa = co->par; icastle_data *data; const char *bname; @@ -4549,7 +4553,7 @@ int sp_illusionary_shapeshift(castorder * co) const race *rc; unit *mage = co->magician.u; int cast_level = co->level; - float power = co->force; + double power = co->force; spellparameter *pa = co->par; const race *irace; @@ -4645,6 +4649,8 @@ int sp_analysedream(castorder * co) return cast_level; } +static int sp_gbdreams(castorder * co, const char *curse_name, int effect); + /* ------------------------------------------------------------- */ /* Name: Schlechte Traeume * Stufe: 10 @@ -4660,28 +4666,7 @@ int sp_analysedream(castorder * co) * */ int sp_baddreams(castorder * co) { - int duration; - unit *mage = co->magician.u; - int cast_level = co->level; - float power = co->force; - region *r = co_get_region(co); - curse *c; - float effect; - - /* wirkt erst in der Folgerunde, soll mindestens eine Runde wirken, - * also duration+2 */ - duration = (int)_max(1, power / 2); /* Stufe 1 macht sonst mist */ - duration = 2 + rng_int() % duration; - - /* Nichts machen als ein entsprechendes Attribut in die Region legen. */ - effect = -1; - c = create_curse(mage, &r->attribs, ct_find("gbdream"), power, duration, effect, 0); - - /* Erfolg melden */ - ADDMSG(&mage->faction->msgs, msg_message("regionmagic_effect", - "unit region command", c->magician, mage->region, co->order)); - - return cast_level; + return sp_gbdreams(co, "gbdream", -1); } /* ------------------------------------------------------------- */ @@ -4697,21 +4682,26 @@ int sp_baddreams(castorder * co) * (FARCASTING | SPELLLEVEL | REGIONSPELL | TESTRESISTANCE) */ int sp_gooddreams(castorder * co) +{ + return sp_gbdreams(co, "gbdream", 1); +} + +static int sp_gbdreams(castorder * co, const char *curse_name, int effect) { int duration; - curse *c; - region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float power = co->force; - float effect; + double power = co->force; + region *r = co_get_region(co); + curse *c; /* wirkt erst in der Folgerunde, soll mindestens eine Runde wirken, * also duration+2 */ duration = (int)_max(1, power / 2); /* Stufe 1 macht sonst mist */ duration = 2 + rng_int() % duration; - effect = 1; - c = create_curse(mage, &r->attribs, ct_find("gbdream"), power, duration, effect, 0); + + /* Nichts machen als ein entsprechendes Attribut in die Region legen. */ + c = create_curse(mage, &r->attribs, ct_find(curse_name), power, duration, effect, 0); /* Erfolg melden */ ADDMSG(&mage->faction->msgs, msg_message("regionmagic_effect", @@ -4771,7 +4761,7 @@ int sp_dreamreading(castorder * co) unit *mage = co->magician.u; int cast_level = co->level; spellparameter *pa = co->par; - float power = co->force; + double power = co->force; message *msg; /* wenn kein Ziel gefunden, Zauber abbrechen */ @@ -4822,7 +4812,7 @@ int sp_sweetdreams(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float power = co->force; + double power = co->force; spellparameter *pa = co->par; int men, n; int duration = (int)(power / 2) + 1; @@ -4832,7 +4822,7 @@ int sp_sweetdreams(castorder * co) for (n = 0; n < pa->length; n++) { curse *c; unit *u; - float effect; + double effect; message *msg; /* sollte nie negativ werden */ if (opfer < 1) @@ -4872,9 +4862,9 @@ int sp_disturbingdreams(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float power = co->force; + double power = co->force; int duration = 1 + (int)(power / 6); - float effect; + double effect; curse *c; effect = 10; @@ -4962,7 +4952,7 @@ int sp_itemcloak(castorder * co) unit *mage = co->magician.u; spellparameter *pa = co->par; int cast_level = co->level; - float power = co->force; + double power = co->force; int duration = (int)_max(2.0, power + 1); /* works in the report, and ageing this round would kill it if it's <=1 */ /* wenn kein Ziel gefunden, Zauber abbrechen */ @@ -5002,7 +4992,7 @@ int sp_resist_magic_bonus(castorder * co) int duration = 6; unit *mage = co->magician.u; int cast_level = co->level; - float power = co->force; + double power = co->force; spellparameter *pa = co->par; /* Pro Stufe koennen bis zu 5 Personen verzaubert werden */ double maxvictims = 5 * power; @@ -5021,12 +5011,6 @@ int sp_resist_magic_bonus(castorder * co) u = pa->param[n]->data.u; - /* Ist die Einheit schon verzaubert, wirkt sich dies nur auf die - * Menge der Verzauberten Personen aus. - if (is_cursed(u->attribs, C_MAGICRESISTANCE, 0)) - continue; - */ - m = _min(u->number, victims); victims -= m; @@ -5062,7 +5046,7 @@ int sp_enterastral(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float power = co->force; + double power = co->force; spellparameter *pa = co->par; switch (getplaneid(r)) { @@ -5177,7 +5161,7 @@ int sp_pullastral(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float power = co->force; + double power = co->force; spellparameter *pa = co->par; switch (getplaneid(r)) { @@ -5319,7 +5303,7 @@ int sp_leaveastral(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float power = co->force; + double power = co->force; spellparameter *pa = co->par; switch (getplaneid(r)) { @@ -5446,7 +5430,7 @@ int sp_fetchastral(castorder * co) unit *mage = co->magician.u; int cast_level = co->level; spellparameter *pa = co->par; - float power = co->force; + double power = co->force; int remaining_cap = (int)((power - 3) * 1500); region_list *rtl = NULL; region *rt = co_get_region(co); /* region to which we are fetching */ @@ -5578,7 +5562,7 @@ int sp_showastral(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float power = co->force; + double power = co->force; switch (getplaneid(r)) { case 0: @@ -5709,7 +5693,7 @@ int sp_disruptastral(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float power = co->force; + double power = co->force; int duration = (int)(power / 3) + 1; switch (getplaneid(r)) { @@ -5734,7 +5718,7 @@ int sp_disruptastral(castorder * co) for (rl2 = rl; rl2 != NULL; rl2 = rl2->next) { attrib *a; - float effect; + double effect; region *r2 = rl2->data; spec_direction *sd; int inhab_regions = 0; @@ -5818,7 +5802,7 @@ static int sp_eternizewall(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float power = co->force; + double power = co->force; spellparameter *pa = co->par; message *msg; @@ -6023,7 +6007,7 @@ int sp_flying_ship(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float power = co->force; + double power = co->force; spellparameter *pa = co->par; message *m = NULL; int cno; @@ -6090,7 +6074,7 @@ int sp_stealaura(castorder * co) unit *u; unit *mage = co->magician.u; int cast_level = co->level; - float power = co->force; + double power = co->force; spellparameter *pa = co->par; /* wenn kein Ziel gefunden, Zauber abbrechen */ @@ -6155,12 +6139,12 @@ int sp_stealaura(castorder * co) */ int sp_antimagiczone(castorder * co) { - float power; - float effect; + double power; + double effect; region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float force = co->force; + double force = co->force; int duration = (int)force + 1; /* Haelt Sprueche bis zu einem summierten Gesamtlevel von power aus. @@ -6169,7 +6153,7 @@ int sp_antimagiczone(castorder * co) power = force * 10; /* Reduziert die Staerke jedes Spruchs um effect */ - effect = (float)cast_level; + effect = cast_level; create_curse(mage, &r->attribs, ct_find("antimagiczone"), power, duration, effect, 0); @@ -6217,9 +6201,9 @@ static int sp_magicrunes(castorder * co) int duration; unit *mage = co->magician.u; int cast_level = co->level; - float force = co->force; + double force = co->force; spellparameter *pa = co->par; - float effect; + double effect; duration = 3 + rng_int() % cast_level; effect = 20; @@ -6277,14 +6261,14 @@ int sp_speed2(castorder * co) unit *u; unit *mage = co->magician.u; int cast_level = co->level; - float force = co->force; + double force = co->force; spellparameter *pa = co->par; maxmen = 2 * cast_level * cast_level; dur = _max(1, cast_level / 2); for (n = 0; n < pa->length; n++) { - float effect; + double effect; /* sollte nie negativ werden */ if (maxmen < 1) break; @@ -6338,7 +6322,7 @@ int sp_q_antimagie(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float force = co->force; + double force = co->force; spellparameter *pa = co->par; const char *ts = NULL; @@ -6418,7 +6402,7 @@ int sp_break_curse(castorder * co) region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; - float force = co->force; + double force = co->force; spellparameter *pa = co->par; const char *ts = NULL; @@ -6599,7 +6583,7 @@ static spelldata spell_functions[] = { { "heroic_song", sp_hero, 0 }, { "transfer_aura_song", sp_transferaura, 0 }, { "analysesong_unit", sp_analysesong_unit, 0 }, - { "cerrdorfumbleshield", sp_fumbleshield, 0 }, + { "cerddorfumbleshield", sp_fumbleshield, 0 }, { "calm_monster", sp_calm_monster, 0 }, { "seduction", sp_seduce, 0 }, { "headache", sp_headache, 0 }, @@ -6777,6 +6761,8 @@ static int sp_readmind(castorder * co) return cast_level; } +void register_magicresistance(void); + void register_spells(void) { register_borders(); @@ -6803,4 +6789,5 @@ void register_spells(void) register_regioncurse(); register_shipcurse(); register_buildingcurse(); + register_magicresistance(); } diff --git a/src/spells.h b/src/spells.h index a23558e96..65270a164 100644 --- a/src/spells.h +++ b/src/spells.h @@ -14,6 +14,10 @@ #ifndef H_SPL_SPELLS #define H_SPL_SPELLS + +#include "magic.h" + + #ifdef __cplusplus extern "C" { #endif @@ -26,6 +30,9 @@ extern "C" { void register_spells(void); void set_spelldata(struct spell *sp); + int sp_baddreams(castorder * co); + int sp_gooddreams(castorder * co); + #define ACTION_RESET 0x01 /* reset the one-time-flag FFL_SELECT (on first pass) */ #define ACTION_CANSEE 0x02 /* to people who can see the actor */ #define ACTION_CANNOTSEE 0x04 /* to people who can not see the actor */ diff --git a/src/spells.test.c b/src/spells.test.c new file mode 100644 index 000000000..5ecb8bd88 --- /dev/null +++ b/src/spells.test.c @@ -0,0 +1,75 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "spells.h" + +#include +#include + +#include +#include +#include +#include + + +static void test_create_castorder(castorder *order, unit *u, int level, float force, int range) { + struct locale * lang; + lang = get_or_create_locale("en"); + create_castorder(order, u, NULL, NULL, u->region, level, force, range, create_order(K_CAST, lang, ""), NULL); +} + +static void test_dreams(CuTest *tc) { + struct region *r; + struct faction *f1, *f2; + unit *u1, *u2; + int level; + castorder order; + + test_cleanup(); + test_create_world(); + r=findregion(0, 0); + f1 = test_create_faction(0); + f2 = test_create_faction(0); + u1 = test_create_unit(f1, r); + u2 = test_create_unit(f2, r); + + test_create_castorder(&order, u1, 10, 10., 0); + level = sp_gooddreams(&order); + CuAssertIntEquals(tc, 10, level); + + curse *curse = get_curse(r->attribs, ct_find("gbdream")); + CuAssertTrue(tc, curse && curse->duration > 1); + CuAssertTrue(tc, curse->effect == 1); + + a_age(&r->attribs); + + CuAssertIntEquals(tc, 1, get_modifier(u1, SK_MELEE, 11, r, false)); + CuAssertIntEquals(tc, 0, get_modifier(u2, SK_MELEE, 11, r, false)); + + test_create_castorder(&order, u1, 10, 10., 0); + level = sp_baddreams(&order); + CuAssertIntEquals(tc, 10, level); + + a_age(&r->attribs); + + CuAssertIntEquals(tc, 1, get_modifier(u1, SK_MELEE, 11, r, false)); + CuAssertIntEquals(tc, -1, get_modifier(u2, SK_MELEE, 11, r, false)); + + free_castorder(&order); + test_cleanup(); +} + +CuSuite *get_spells_suite(void) +{ + CuSuite *suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_dreams); + return suite; +} diff --git a/src/spells/CMakeLists.txt b/src/spells/CMakeLists.txt index 0fbd5c5a0..335189c21 100644 --- a/src/spells/CMakeLists.txt +++ b/src/spells/CMakeLists.txt @@ -7,6 +7,7 @@ combatspells.c regioncurse.c shipcurse.c unitcurse.c +magicresistance.c ) FOREACH(_FILE ${_FILES}) LIST(APPEND _SOURCES ${PROJECT_NAME}/${_FILE}) diff --git a/src/spells/borders.c b/src/spells/borders.c index 5994e2b14..d1b5625cc 100644 --- a/src/spells/borders.c +++ b/src/spells/borders.c @@ -29,7 +29,7 @@ typedef struct wallcurse { connection *wall; } wallcurse; -void cw_init(attrib * a) +static void cw_init(attrib * a) { curse *c; curse_init(a); @@ -37,7 +37,7 @@ void cw_init(attrib * a) c->data.v = calloc(sizeof(wallcurse), 1); } -void cw_write(const attrib * a, const void *target, storage * store) +static void cw_write(const attrib * a, const void *target, storage * store) { connection *b = ((wallcurse *)((curse *)a->data.v)->data.v)->wall; curse_write(a, target, store); @@ -86,7 +86,7 @@ static int cw_read(attrib * a, void *target, storage * store) * Was fuer eine Wirkung hat die? */ -void wall_vigour(curse * c, float delta) +static void wall_vigour(curse * c, double delta) { wallcurse *wc = (wallcurse *)c->data.v; assert(wc->buddy->vigour == c->vigour); @@ -105,7 +105,7 @@ const curse_type ct_firewall = { wall_vigour /* change_vigour */ }; -attrib_type at_cursewall = { +static attrib_type at_cursewall = { "cursewall", cw_init, curse_done, diff --git a/src/spells/buildingcurse.c b/src/spells/buildingcurse.c index 0f7a17f5b..d3b5ddf36 100644 --- a/src/spells/buildingcurse.c +++ b/src/spells/buildingcurse.c @@ -33,16 +33,16 @@ #include #include -static message *cinfo_building(const void *obj, objtype_t typ, const curse * c, +message *cinfo_building(const void *obj, objtype_t typ, const curse * c, int self) { + const building *b = (const building *)obj; unused_arg(typ); assert(typ == TYP_BUILDING); + assert(obj); + assert(c); - if (self != 0) { /* owner or inside */ - return msg_message(mkname("curseinfo", c->type->cname), "id", c->no); - } - return msg_message(mkname("curseinfo", "buildingunknown"), "id", c->no); + return msg_message(mkname("curseinfo", self ? c->type->cname : "buildingunknown"), "id building", c->no, b); } /* CurseInfo mit Spezialabfragen */ diff --git a/src/spells/buildingcurse.h b/src/spells/buildingcurse.h index d6366c920..46989829a 100644 --- a/src/spells/buildingcurse.h +++ b/src/spells/buildingcurse.h @@ -13,14 +13,17 @@ #ifndef _BCURSE_H #define _BCURSE_H +#include #ifdef __cplusplus extern "C" { #endif struct locale; struct curse; + struct message; extern void register_buildingcurse(void); + struct message *cinfo_building(const void *obj, objtype_t typ, const struct curse * c, int self); #ifdef __cplusplus } diff --git a/src/spells/combatspells.c b/src/spells/combatspells.c index 21410465d..feed41ef0 100644 --- a/src/spells/combatspells.c +++ b/src/spells/combatspells.c @@ -908,11 +908,11 @@ int sp_strong_wall(struct castorder * co) { fighter * fi = co->magician.fig; int level = co->level; - float power = co->force; + double power = co->force; battle *b = fi->side->battle; unit *mage = fi->unit; building *burg; - float effect; + double effect; static bool init = false; message *msg; static const curse_type *strongwall_ct; @@ -1504,7 +1504,7 @@ int sp_fumbleshield(struct castorder * co) switch (sp->id) { case SPL_DRAIG_FUMBLESHIELD: case SPL_GWYRRD_FUMBLESHIELD: - case SPL_CERRDOR_FUMBLESHIELD: + case SPL_CERDDOR_FUMBLESHIELD: case SPL_TYBIED_FUMBLESHIELD: duration = 100; effect = _max(1, 25 - level); @@ -1748,7 +1748,7 @@ int sp_undeadhero(struct castorder * co) if (j > 0) { item **ilist; unit *u = - create_unit(r, mage->faction, 0, get_race(RC_UNDEAD), 0, du->name, + create_unit(r, mage->faction, 0, get_race(RC_UNDEAD), 0, unit_getname(du), du); /* new units gets some stats from old unit */ diff --git a/src/spells/magicresistance.c b/src/spells/magicresistance.c new file mode 100644 index 000000000..0a4ffaa9f --- /dev/null +++ b/src/spells/magicresistance.c @@ -0,0 +1,31 @@ +#include +#include +#include +#include +#include + +static struct message *cinfo_magicresistance(const void *obj, objtype_t typ, const struct curse * c, int self) +{ + if (typ == TYP_UNIT) { + if (self != 0) { + const struct unit *u = (const struct unit *)obj; + return msg_message(mkname("curseinfo", c->type->cname), "unit id", u, + c->no); + } + return NULL; + } + if (typ == TYP_BUILDING) { + const struct building *b = (const struct building *)obj; + return msg_message(mkname("curseinfo", self ? "homestone" : "buildingunknown"), "id building", c->no, b); + } + return 0; +} + +static struct curse_type ct_magicresistance = { + "magicresistance", CURSETYP_UNIT, CURSE_SPREADMODULO, M_MEN, cinfo_magicresistance +}; + +void register_magicresistance(void) +{ + ct_register(&ct_magicresistance); +} diff --git a/src/spells/magicresistance.test.c b/src/spells/magicresistance.test.c new file mode 100644 index 000000000..72269718c --- /dev/null +++ b/src/spells/magicresistance.test.c @@ -0,0 +1,83 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "spells.h" + +#include +#include + +#include +#include +#include +#include + + +static void test_magicresistance_unit(CuTest *tc) { + struct region *r; + struct faction *f1, *f2; + unit *u1, *u2; + message *msg; + curse *c; + + test_cleanup(); + test_create_world(); + r=findregion(0, 0); + f1 = test_create_faction(test_create_race("human")); + u1 = test_create_unit(f1, r); + + f2 = test_create_faction(test_create_race("human")); + u2 = test_create_unit(f2, r); + + c = create_curse(u1, &u2->attribs, ct_find("magicresistance"), 10, 20, 30, u2->number); + CuAssertPtrNotNull(tc, u2->attribs); + CuAssertPtrEquals(tc, (void *)&at_curse, (void *)u2->attribs->type); + msg = c->type->curseinfo(u2, TYP_UNIT, c, 1); + CuAssertPtrNotNull(tc, msg); + CuAssertStrEquals(tc, "curseinfo::magicresistance", test_get_messagetype(msg)); + + test_cleanup(); +} + +static void test_magicresistance_building(CuTest *tc) { + struct region *r; + struct faction *f1; + unit *u1; + building *b1; + message *msg; + curse *c; + + test_cleanup(); + test_create_world(); + r = findregion(0, 0); + f1 = test_create_faction(test_create_race("human")); + u1 = test_create_unit(f1, r); + + b1 = test_create_building(r, test_create_buildingtype("castle")); + + c = create_curse(u1, &b1->attribs, ct_find("magicresistance"), 10, 20, 30, 0); + CuAssertPtrNotNull(tc, b1->attribs); + CuAssertPtrEquals(tc, (void *)&at_curse, (void *)b1->attribs->type); + msg = c->type->curseinfo(b1, TYP_BUILDING, c, 1); + CuAssertPtrNotNull(tc, msg); + CuAssertStrEquals(tc, "curseinfo::homestone", test_get_messagetype(msg)); + + test_cleanup(); +} + +CuSuite *get_magicresistance_suite(void) +{ + CuSuite *suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_magicresistance_unit); + SUITE_ADD_TEST(suite, test_magicresistance_building); + return suite; +} diff --git a/src/spells/shipcurse.c b/src/spells/shipcurse.c index e79990fd6..29e4ad8f8 100644 --- a/src/spells/shipcurse.c +++ b/src/spells/shipcurse.c @@ -121,7 +121,7 @@ static struct curse_type ct_shipspeedup = { "shipspeedup", CURSETYP_NORM, 0, 0, cinfo_ship }; -curse *shipcurse_flyingship(ship * sh, unit * mage, float power, int duration) +curse *shipcurse_flyingship(ship * sh, unit * mage, double power, int duration) { static const curse_type *ct_flyingship = NULL; if (!ct_flyingship) { @@ -146,7 +146,7 @@ curse *shipcurse_flyingship(ship * sh, unit * mage, float power, int duration) } } -int levitate_ship(ship * sh, unit * mage, float power, int duration) +int levitate_ship(ship * sh, unit * mage, double power, int duration) { curse *c = shipcurse_flyingship(sh, mage, power, duration); if (c) { diff --git a/src/spells/shipcurse.h b/src/spells/shipcurse.h index b64b3fd79..676cd7344 100644 --- a/src/spells/shipcurse.h +++ b/src/spells/shipcurse.h @@ -29,8 +29,8 @@ extern "C" { const struct curse *c, int self); void register_shipcurse(void); struct curse *shipcurse_flyingship(struct ship *sh, struct unit *mage, - float power, int duration); - int levitate_ship(struct ship *sh, struct unit *mage, float power, + double power, int duration); + int levitate_ship(struct ship *sh, struct unit *mage, double power, int duration); #ifdef __cplusplus diff --git a/src/spells/unitcurse.c b/src/spells/unitcurse.c index bd332ebf5..73925a55a 100644 --- a/src/spells/unitcurse.c +++ b/src/spells/unitcurse.c @@ -159,6 +159,7 @@ message *cinfo_unit(const void *obj, objtype_t typ, const curse * c, int self) { unused_arg(typ); assert(typ == TYP_UNIT); + assert(obj); if (self != 0) { unit *u = (unit *)obj; @@ -301,10 +302,6 @@ static struct curse_type ct_oldrace = { "oldrace", CURSETYP_NORM, CURSE_SPREADALWAYS, NO_MERGE, NULL }; -static struct curse_type ct_magicresistance = { - "magicresistance", CURSETYP_UNIT, CURSE_SPREADMODULO, M_MEN, cinfo_simple -}; - /* ------------------------------------------------------------- */ /* * C_SKILL @@ -365,5 +362,4 @@ void register_unitcurse(void) ct_register(&ct_itemcloak); ct_register(&ct_fumble); ct_register(&ct_oldrace); - ct_register(&ct_magicresistance); } diff --git a/src/spy.c b/src/spy.c index 601deff65..a440ab3aa 100644 --- a/src/spy.c +++ b/src/spy.c @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 1998-2015, Enno Rehling Katja Zedel @@ -53,6 +53,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include #include +#include /* in spy steht der Unterschied zwischen Wahrnehmung des Opfers und * Spionage des Spions */ @@ -66,7 +67,7 @@ void spy_message(int spy, const unit * u, const unit * target) sc_mage *mage = get_mage(target); /* for mages, spells and magic school */ if (mage) { - ADDMSG(&u->faction->msgs, msg_message("spyreport_mage", "target type", + ADDMSG(&u->faction->msgs, msg_message("spyreport_mage", "spy target type", u, target, magic_school[mage->magietyp])); } } @@ -75,7 +76,7 @@ void spy_message(int spy, const unit * u, const unit * target) if (fv && fv != target->faction) { /* true faction */ ADDMSG(&u->faction->msgs, msg_message("spyreport_faction", - "target faction", target, target->faction)); + "spy target faction", u, target, target->faction)); add_seen_faction(u->faction, target->faction); } } @@ -103,12 +104,12 @@ void spy_message(int spy, const unit * u, const unit * target) } } if (found) { - ADDMSG(&u->faction->msgs, msg_message("spyreport_skills", "target skills", + ADDMSG(&u->faction->msgs, msg_message("spyreport_skills", "spy target skills", u, target, buf)); } if (target->items) { - ADDMSG(&u->faction->msgs, msg_message("spyreport_items", "target items", + ADDMSG(&u->faction->msgs, msg_message("spyreport_items", "spy target items", u, target, target->items)); } } @@ -375,7 +376,7 @@ static int try_destruction(unit * u, unit * u2, const ship * sh, int skilldiff) } else if (skilldiff < 0) { /* tell the unit that the attempt was detected: */ - ADDMSG(&u2->faction->msgs, msg_message(destruction_detected_msg, + ADDMSG(&u->faction->msgs, msg_message(destruction_detected_msg, "ship unit", sh, u)); /* tell the enemy whodunit: */ if (u2) { @@ -394,7 +395,7 @@ static int try_destruction(unit * u, unit * u2, const ship * sh, int skilldiff) return 1; /* success */ } -static void sink_ship(region * r, ship * sh, const char *name, unit * saboteur) +static void sink_ship(region * r, ship * sh, unit * saboteur) { unit **ui, *u; region *safety = r; @@ -404,6 +405,9 @@ static void sink_ship(region * r, ship * sh, const char *name, unit * saboteur) message *sink_msg = NULL; faction *f; + assert(r); + assert(sh); + assert(saboteur); for (f = NULL, u = r->units; u; u = u->next) { /* slight optimization to avoid dereferencing u->faction each time */ if (f != u->faction) { @@ -426,7 +430,7 @@ static void sink_ship(region * r, ship * sh, const char *name, unit * saboteur) } } } - for (ui = &r->units; *ui; ui = &(*ui)->next) { + for (ui = &r->units; *ui;) { unit *u = *ui; /* inform this faction about the sinking ship: */ @@ -471,12 +475,13 @@ static void sink_ship(region * r, ship * sh, const char *name, unit * saboteur) add_message(&u->faction->msgs, msg); msg_release(msg); if (dead == u->number) { - /* the poor creature, she dies */ - if (remove_unit(ui, u) != 0) { - ui = &u->next; + if (remove_unit(ui, u) == 0) { + /* ui is already pointing at u->next */ + continue; } } } + ui = &u->next; } if (sink_msg) msg_release(sink_msg); @@ -487,19 +492,21 @@ static void sink_ship(region * r, ship * sh, const char *name, unit * saboteur) int sabotage_cmd(unit * u, struct order *ord) { const char *s; - int i; + param_t p; ship *sh; unit *u2; - char buffer[DISPLAYSIZE]; - region *r = u->region; - int skdiff; + region *r; + int skdiff = INT_MAX; + + assert(u); + assert(ord); init_order(ord); s = getstrtoken(); - i = findparam(s, u->faction->locale); + p = findparam(s, u->faction->locale); - switch (i) { + switch (p) { case P_SHIP: sh = u->ship; if (!sh) { @@ -507,10 +514,13 @@ int sabotage_cmd(unit * u, struct order *ord) return 0; } u2 = ship_owner(sh); - skdiff = - eff_skill(u, SK_SPY, r) - crew_skill(r, u2->faction, sh, SK_PERCEPTION); + r = u->region; + if (u2->faction != u->faction) { + skdiff = + eff_skill(u, SK_SPY, r) - crew_skill(r, u2->faction, sh, SK_PERCEPTION); + } if (try_destruction(u, u2, sh, skdiff)) { - sink_ship(r, sh, buffer, u); + sink_ship(r, sh, u); } break; default: diff --git a/src/spy.test.c b/src/spy.test.c new file mode 100644 index 000000000..085cc5675 --- /dev/null +++ b/src/spy.test.c @@ -0,0 +1,197 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "spy.h" + +#include +#include + +#include + +typedef enum { + M_BASE, + M_MAGE, + M_SKILLS, + M_FACTION, + M_ITEMS, + NUM_TYPES +} m_type; + +typedef struct { + region *r; + unit *spy; + unit *victim; + const message_type *msg_types[NUM_TYPES]; +} spy_fixture; + +static void setup_spy(spy_fixture *fix) { + test_cleanup(); + fix->r = test_create_region(0, 0, NULL); + fix->spy = test_create_unit(test_create_faction(NULL), fix->r); + fix->victim = test_create_unit(test_create_faction(NULL), fix->r); + fix->msg_types[M_BASE] = register_msg("spyreport", 3, "spy:unit", "target:unit", "status:string"); + fix->msg_types[M_MAGE] = register_msg("spyreport_mage", 3, "spy:unit", "target:unit", "type:string"); + fix->msg_types[M_SKILLS] = register_msg("spyreport_skills", 3, "spy:unit", "target:unit", "skills:string"); + fix->msg_types[M_FACTION] = register_msg("spyreport_faction", 3, "spy:unit", "target:unit", "faction:faction"); + fix->msg_types[M_ITEMS] = register_msg("spyreport_items", 3, "spy:unit", "target:unit", "items:items"); + +} + +static void test_simple_spy_message(CuTest *tc) { + spy_fixture fix; + + setup_spy(&fix); + + spy_message(0, fix.spy, fix.victim); + + assert_messages(tc, fix.spy->faction->msgs->begin, fix.msg_types, 1, true, M_BASE); + + + test_cleanup(); +} + +static void set_factionstealth(unit *u, faction *f) { + attrib *a = a_find(u->attribs, &at_otherfaction); + if (!a) + a = a_add(&u->attribs, make_otherfaction(f)); + else + a->data.v = f; +} + +static void test_all_spy_message(CuTest *tc) { + spy_fixture fix; + + setup_spy(&fix); + + enable_skill(SK_MAGIC, true); + set_level(fix.victim, SK_MINING, 2); + set_level(fix.victim, SK_MAGIC, 2); + create_mage(fix.victim, M_DRAIG); + set_factionstealth(fix.victim, fix.spy->faction); + + item_type *itype; + itype = it_get_or_create(rt_get_or_create("sword")); + new_weapontype(itype, 0, 0.0, NULL, 0, 0, 0, SK_MELEE, 2); + i_change(&fix.victim->items, itype, 1); + + spy_message(99, fix.spy, fix.victim); + + assert_messages(tc, fix.spy->faction->msgs->begin, fix.msg_types, 5, true, + M_BASE, + M_MAGE, + M_FACTION, + M_SKILLS, + M_ITEMS); + + test_cleanup(); +} + +static void setup_sabotage(void) { + struct locale *lang; + + test_cleanup(); + lang = get_or_create_locale("de"); + locale_setstring(lang, parameters[P_SHIP], "SCHIFF"); + test_create_world(); + init_locales(); +} + +static void test_sabotage_self(CuTest *tc) { + unit *u; + region *r; + order *ord; + + setup_sabotage(); + r = test_create_region(0, 0, NULL); + assert(r); + u = test_create_unit(test_create_faction(NULL), r); + assert(u && u->faction && u->region == r); + u->ship = test_create_ship(r, test_create_shiptype("boat")); + assert(u->ship); + ord = create_order(K_SABOTAGE, u->faction->locale, "SCHIFF"); + assert(ord); + CuAssertIntEquals(tc, 0, sabotage_cmd(u, ord)); + CuAssertPtrEquals(tc, 0, r->ships); + test_cleanup(); +} + + +static void test_sabotage_other_fail(CuTest *tc) { + unit *u, *u2; + region *r; + order *ord; + message *msg; + + setup_sabotage(); + r = test_create_region(0, 0, NULL); + assert(r); + u = test_create_unit(test_create_faction(NULL), r); + u2 = test_create_unit(test_create_faction(NULL), r); + assert(u && u2); + u2->ship = test_create_ship(r, test_create_shiptype("boat")); + assert(u2->ship); + u->ship = u2->ship; + ship_update_owner(u->ship); + assert(ship_owner(u->ship) == u); + ord = create_order(K_SABOTAGE, u->faction->locale, "SCHIFF"); + assert(ord); + CuAssertIntEquals(tc, 0, sabotage_cmd(u2, ord)); + msg = test_get_last_message(u2->faction->msgs); + CuAssertStrEquals(tc, "destroy_ship_1", test_get_messagetype(msg)); + msg = test_get_last_message(u->faction->msgs); + CuAssertStrEquals(tc, "destroy_ship_3", test_get_messagetype(msg)); + CuAssertPtrNotNull(tc, r->ships); + test_cleanup(); +} + + +static void test_sabotage_other_success(CuTest *tc) { + unit *u, *u2; + region *r; + order *ord; + + setup_sabotage(); + r = test_create_region(0, 0, NULL); + assert(r); + u = test_create_unit(test_create_faction(NULL), r); + u2 = test_create_unit(test_create_faction(NULL), r); + assert(u && u2); + u2->ship = test_create_ship(r, test_create_shiptype("boat")); + assert(u2->ship); + u->ship = u2->ship; + ship_update_owner(u->ship); + assert(ship_owner(u->ship) == u); + ord = create_order(K_SABOTAGE, u->faction->locale, "SCHIFF"); + assert(ord); + set_level(u2, SK_SPY, 1); + CuAssertIntEquals(tc, 0, sabotage_cmd(u2, ord)); + CuAssertPtrEquals(tc, 0, r->ships); + test_cleanup(); +} + +CuSuite *get_spy_suite(void) +{ + CuSuite *suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_simple_spy_message); + SUITE_ADD_TEST(suite, test_all_spy_message); + SUITE_ADD_TEST(suite, test_sabotage_self); + SUITE_ADD_TEST(suite, test_sabotage_other_fail); + SUITE_ADD_TEST(suite, test_sabotage_other_success); + return suite; +} diff --git a/src/sqlite.c b/src/sqlite.c index c19aa6903..fd46c4f1f 100644 --- a/src/sqlite.c +++ b/src/sqlite.c @@ -123,9 +123,9 @@ static void update_faction(sqlite3 *db, const faction *f) { "INSERT INTO faction_data (faction_id, code, name, email, lang, turn)" " VALUES (?, ?, ?, ?, ?, ?)"; sqlite3_stmt *stmt = 0; + strcpy(code, itoa36(f->no)); sqlite3_prepare_v2(db, sql, -1, &stmt, 0); sqlite3_bind_int(stmt, 1, f->subscription); - strcpy(code, itoa36(f->no)); sqlite3_bind_text(stmt, 2, code, -1, SQLITE_STATIC); sqlite3_bind_text(stmt, 3, f->name, -1, SQLITE_STATIC); sqlite3_bind_text(stmt, 4, f->email, -1, SQLITE_STATIC); diff --git a/src/study.c b/src/study.c index 4a0874a5a..ec377f0f7 100644 --- a/src/study.c +++ b/src/study.c @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 1998-2015, Enno Rehling Katja Zedel @@ -42,6 +42,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include #include +#include #include #include #include @@ -217,8 +218,12 @@ bool report, int *academy) } if (index < MAXTEACHERS) teach->teachers[index++] = teacher; - if (index < MAXTEACHERS) + if (index < MAXTEACHERS) { teach->teachers[index] = NULL; + } + else { + log_warning("MAXTEACHERS is too low at %d", MAXTEACHERS); + } teach->value += n; /* Solange Akademien groessenbeschraenkt sind, sollte Lehrer und @@ -512,7 +517,7 @@ static double study_speedup(unit * u, skill_t s, study_rule_t rule) if (rule == STUDY_AUTOTEACH) { for (i = 0; i != u->skill_size; ++i) { skill *sv = u->skills + i; - learnweeks = +(sv->level * (sv->level + 1) / 2.0); + learnweeks += (sv->level * (sv->level + 1) / 2.0); } if (learnweeks < turn / 2) { return 2.0; @@ -537,6 +542,9 @@ int learn_cmd(unit * u, order * ord) int maxalchemy = 0; int speed_rule = (study_rule_t)get_param_int(global.parameters, "study.speedup", 0); static int learn_newskills = -1; + struct building *b = inside_building(u); + const struct building_type *btype = b ? b->type : NULL; + if (learn_newskills < 0) { const char *str = get_param(global.parameters, "study.newskills"); if (str && strcmp(str, "false") == 0) @@ -598,220 +606,217 @@ int learn_cmd(unit * u, order * ord) return 0; } /* Akademie: */ - { - struct building *b = inside_building(u); - const struct building_type *btype = b ? b->type : NULL; + b = inside_building(u); + btype = b ? b->type : NULL; - if (btype && btype == bt_find("academy")) { - studycost = _max(50, studycost * 2); - } - } + if (btype && btype == bt_find("academy")) { + studycost = _max(50, studycost * 2); + } - if (sk == SK_MAGIC) { - if (u->number > 1) { - cmistake(u, ord, 106, MSG_MAGIC); - return 0; - } - if (is_familiar(u)) { - /* Vertraute zaehlen nicht zu den Magiern einer Partei, - * koennen aber nur Graue Magie lernen */ - mtyp = M_GRAY; - if (!is_mage(u)) - create_mage(u, mtyp); - } - else if (!has_skill(u, SK_MAGIC)) { - int mmax = skill_limit(u->faction, SK_MAGIC); - /* Die Einheit ist noch kein Magier */ - if (count_skill(u->faction, SK_MAGIC) + u->number > mmax) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_max_magicians", - "amount", mmax)); - return 0; - } - mtyp = getmagicskill(u->faction->locale); - if (mtyp == M_NONE || mtyp == M_GRAY) { - /* wurde kein Magiegebiet angegeben, wird davon - * ausgegangen, dass das normal gelernt werden soll */ - if (u->faction->magiegebiet != 0) { - mtyp = u->faction->magiegebiet; - } - else { - /* Es wurde kein Magiegebiet angegeben und die Partei - * hat noch keins gewaehlt. */ - mtyp = getmagicskill(u->faction->locale); - if (mtyp == M_NONE) { - cmistake(u, ord, 178, MSG_MAGIC); - return 0; - } - } - } - if (mtyp != u->faction->magiegebiet) { - /* Es wurde versucht, ein anderes Magiegebiet zu lernen - * als das der Partei */ - if (u->faction->magiegebiet != 0) { - cmistake(u, ord, 179, MSG_MAGIC); - return 0; - } - else { - /* Lernt zum ersten mal Magie und legt damit das - * Magiegebiet der Partei fest */ - u->faction->magiegebiet = mtyp; - } - } - if (!is_mage(u)) - create_mage(u, mtyp); - } - else { - /* ist schon ein Magier und kein Vertrauter */ - if (u->faction->magiegebiet == 0) { - /* die Partei hat noch kein Magiegebiet gewaehlt. */ - mtyp = getmagicskill(u->faction->locale); - if (mtyp == M_NONE) { - mtyp = getmagicskill(u->faction->locale); - if (mtyp == M_NONE) { - cmistake(u, ord, 178, MSG_MAGIC); - return 0; - } - } - /* Legt damit das Magiegebiet der Partei fest */ - u->faction->magiegebiet = mtyp; - } - } - } - if (sk == SK_ALCHEMY) { - maxalchemy = eff_skill(u, SK_ALCHEMY, r); - if (!has_skill(u, SK_ALCHEMY)) { - int amax = skill_limit(u->faction, SK_ALCHEMY); - if (count_skill(u->faction, SK_ALCHEMY) + u->number > amax) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_max_alchemists", - "amount", amax)); - return 0; - } - } - } - if (studycost) { - int cost = studycost * u->number; - money = get_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, cost); - money = _min(money, cost); - } - if (money < studycost * u->number) { - studycost = p; /* Ohne Univertreurung */ - money = _min(money, studycost); - if (p > 0 && money < studycost * u->number) { - cmistake(u, ord, 65, MSG_EVENT); - multi = money / (double)(studycost * u->number); - } - } + if (sk == SK_MAGIC) { + if (u->number > 1) { + cmistake(u, ord, 106, MSG_MAGIC); + return 0; + } + if (is_familiar(u)) { + /* Vertraute zaehlen nicht zu den Magiern einer Partei, + * koennen aber nur Graue Magie lernen */ + mtyp = M_GRAY; + if (!is_mage(u)) + create_mage(u, mtyp); + } + else if (!has_skill(u, SK_MAGIC)) { + int mmax = skill_limit(u->faction, SK_MAGIC); + /* Die Einheit ist noch kein Magier */ + if (count_skill(u->faction, SK_MAGIC) + u->number > mmax) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_max_magicians", + "amount", mmax)); + return 0; + } + mtyp = getmagicskill(u->faction->locale); + if (mtyp == M_NONE || mtyp == M_GRAY) { + /* wurde kein Magiegebiet angegeben, wird davon + * ausgegangen, dass das normal gelernt werden soll */ + if (u->faction->magiegebiet != 0) { + mtyp = u->faction->magiegebiet; + } + else { + /* Es wurde kein Magiegebiet angegeben und die Partei + * hat noch keins gewaehlt. */ + mtyp = getmagicskill(u->faction->locale); + if (mtyp == M_NONE) { + cmistake(u, ord, 178, MSG_MAGIC); + return 0; + } + } + } + if (mtyp != u->faction->magiegebiet) { + /* Es wurde versucht, ein anderes Magiegebiet zu lernen + * als das der Partei */ + if (u->faction->magiegebiet != 0) { + cmistake(u, ord, 179, MSG_MAGIC); + return 0; + } + else { + /* Lernt zum ersten mal Magie und legt damit das + * Magiegebiet der Partei fest */ + u->faction->magiegebiet = mtyp; + } + } + if (!is_mage(u)) + create_mage(u, mtyp); + } + else { + /* ist schon ein Magier und kein Vertrauter */ + if (u->faction->magiegebiet == 0) { + /* die Partei hat noch kein Magiegebiet gewaehlt. */ + mtyp = getmagicskill(u->faction->locale); + if (mtyp == M_NONE) { + mtyp = getmagicskill(u->faction->locale); + if (mtyp == M_NONE) { + cmistake(u, ord, 178, MSG_MAGIC); + return 0; + } + } + /* Legt damit das Magiegebiet der Partei fest */ + u->faction->magiegebiet = mtyp; + } + } + } + if (sk == SK_ALCHEMY) { + maxalchemy = eff_skill(u, SK_ALCHEMY, r); + if (!has_skill(u, SK_ALCHEMY)) { + int amax = skill_limit(u->faction, SK_ALCHEMY); + if (count_skill(u->faction, SK_ALCHEMY) + u->number > amax) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_max_alchemists", + "amount", amax)); + return 0; + } + } + } + if (studycost) { + int cost = studycost * u->number; + money = get_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, cost); + money = _min(money, cost); + } + if (money < studycost * u->number) { + studycost = p; /* Ohne Univertreurung */ + money = _min(money, studycost); + if (p > 0 && money < studycost * u->number) { + cmistake(u, ord, 65, MSG_EVENT); + multi = money / (double)(studycost * u->number); + } + } - if (teach == NULL) { - a = a_add(&u->attribs, a_new(&at_learning)); - teach = (teaching_info *)a->data.v; - teach->teachers[0] = 0; - } - if (money > 0) { - use_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, money); - ADDMSG(&u->faction->msgs, msg_message("studycost", - "unit region cost skill", u, u->region, money, sk)); - } + if (teach == NULL) { + a = a_add(&u->attribs, a_new(&at_learning)); + teach = (teaching_info *)a->data.v; + assert(teach); + teach->teachers[0] = 0; + } + if (money > 0) { + use_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, money); + ADDMSG(&u->faction->msgs, msg_message("studycost", + "unit region cost skill", u, u->region, money, sk)); + } - if (get_effect(u, oldpotiontype[P_WISE])) { - l = _min(u->number, get_effect(u, oldpotiontype[P_WISE])); - teach->value += l * 10; - change_effect(u, oldpotiontype[P_WISE], -l); - } - if (get_effect(u, oldpotiontype[P_FOOL])) { - l = _min(u->number, get_effect(u, oldpotiontype[P_FOOL])); - teach->value -= l * 30; - change_effect(u, oldpotiontype[P_FOOL], -l); - } + if (get_effect(u, oldpotiontype[P_WISE])) { + l = _min(u->number, get_effect(u, oldpotiontype[P_WISE])); + teach->value += l * 10; + change_effect(u, oldpotiontype[P_WISE], -l); + } + if (get_effect(u, oldpotiontype[P_FOOL])) { + l = _min(u->number, get_effect(u, oldpotiontype[P_FOOL])); + teach->value -= l * 30; + change_effect(u, oldpotiontype[P_FOOL], -l); + } - if (p != studycost) { - /* ist_in_gebaeude(r, u, BT_UNIVERSITAET) == 1) { */ - /* p ist Kosten ohne Uni, studycost mit; wenn - * p!=studycost, ist die Einheit zwangsweise - * in einer Uni */ - teach->value += u->number * 10; - } + if (p != studycost) { + /* ist_in_gebaeude(r, u, BT_UNIVERSITAET) == 1) { */ + /* p ist Kosten ohne Uni, studycost mit; wenn + * p!=studycost, ist die Einheit zwangsweise + * in einer Uni */ + teach->value += u->number * 10; + } - if (is_cursed(r->attribs, C_BADLEARN, 0)) { - teach->value -= u->number * 10; - } + if (is_cursed(r->attribs, C_BADLEARN, 0)) { + teach->value -= u->number * 10; + } - multi *= study_speedup(u, sk, speed_rule); - days = study_days(u, sk); - days = (int)((days + teach->value) * multi); + multi *= study_speedup(u, sk, speed_rule); + days = study_days(u, sk); + days = (int)((days + teach->value) * multi); - /* the artacademy currently improves the learning of entertainment - of all units in the region, to be able to make it cumulative with - with an academy */ + /* the artacademy currently improves the learning of entertainment + of all units in the region, to be able to make it cumulative with + with an academy */ - if (sk == SK_ENTERTAINMENT - && buildingtype_exists(r, bt_find("artacademy"), false)) { - days *= 2; - } + if (sk == SK_ENTERTAINMENT + && buildingtype_exists(r, bt_find("artacademy"), false)) { + days *= 2; + } - if (fval(u, UFL_HUNGER)) - days /= 2; + if (fval(u, UFL_HUNGER)) + days /= 2; - while (days) { - if (days >= u->number * 30) { - learn_skill(u, sk, 1.0); - days -= u->number * 30; - } - else { - double chance = (double)days / u->number / 30; - learn_skill(u, sk, chance); - days = 0; - } - } - if (a != NULL) { - if (teach != NULL) { - int index = 0; - while (teach->teachers[index] && index != MAXTEACHERS) { - unit *teacher = teach->teachers[index++]; - if (teacher->faction != u->faction) { - bool feedback = alliedunit(u, teacher->faction, HELP_GUARD); - if (feedback) { - ADDMSG(&teacher->faction->msgs, msg_message("teach_teacher", - "teacher student skill level", teacher, u, sk, - effskill(u, sk))); - } - ADDMSG(&u->faction->msgs, msg_message("teach_student", - "teacher student skill", teacher, u, sk)); - } - } - } - a_remove(&u->attribs, a); - a = NULL; - } - fset(u, UFL_LONGACTION | UFL_NOTMOVING); + while (days) { + if (days >= u->number * 30) { + learn_skill(u, sk, 1.0); + days -= u->number * 30; + } + else { + double chance = (double)days / u->number / 30; + learn_skill(u, sk, chance); + days = 0; + } + } + if (a != NULL) { + int index = 0; + while (teach->teachers[index] && index != MAXTEACHERS) { + unit *teacher = teach->teachers[index++]; + if (teacher->faction != u->faction) { + bool feedback = alliedunit(u, teacher->faction, HELP_GUARD); + if (feedback) { + ADDMSG(&teacher->faction->msgs, msg_message("teach_teacher", + "teacher student skill level", teacher, u, sk, + effskill(u, sk))); + } + ADDMSG(&u->faction->msgs, msg_message("teach_student", + "teacher student skill", teacher, u, sk)); + } + } + a_remove(&u->attribs, a); + a = NULL; + } + fset(u, UFL_LONGACTION | UFL_NOTMOVING); - /* Anzeigen neuer Traenke */ - /* Spruchlistenaktualiesierung ist in Regeneration */ + /* Anzeigen neuer Traenke */ + /* Spruchlistenaktualiesierung ist in Regeneration */ - if (sk == SK_ALCHEMY) { - const potion_type *ptype; - faction *f = u->faction; - int skill = eff_skill(u, SK_ALCHEMY, r); - if (skill > maxalchemy) { - for (ptype = potiontypes; ptype; ptype = ptype->next) { - if (skill == ptype->level * 2) { - attrib *a = a_find(f->attribs, &at_showitem); - while (a && a->type == &at_showitem && a->data.v != ptype) - a = a->next; - if (a == NULL || a->type != &at_showitem) { - a = a_add(&f->attribs, a_new(&at_showitem)); - a->data.v = (void *)ptype->itype; - } - } - } - } - } - else if (sk == SK_MAGIC) { - sc_mage *mage = get_mage(u); - if (!mage) { - mage = create_mage(u, u->faction->magiegebiet); - } - } + if (sk == SK_ALCHEMY) { + const potion_type *ptype; + faction *f = u->faction; + int skill = eff_skill(u, SK_ALCHEMY, r); + if (skill > maxalchemy) { + for (ptype = potiontypes; ptype; ptype = ptype->next) { + if (skill == ptype->level * 2) { + attrib *a = a_find(f->attribs, &at_showitem); + while (a && a->type == &at_showitem && a->data.v != ptype) + a = a->next; + if (a == NULL || a->type != &at_showitem) { + a = a_add(&f->attribs, a_new(&at_showitem)); + a->data.v = (void *)ptype->itype; + } + } + } + } + } + else if (sk == SK_MAGIC) { + sc_mage *mage = get_mage(u); + if (!mage) { + mage = create_mage(u, u->faction->magiegebiet); + } + } - return 0; + return 0; } diff --git a/src/study.h b/src/study.h index dce5c0b34..d5d664fd2 100644 --- a/src/study.h +++ b/src/study.h @@ -32,7 +32,7 @@ extern "C" { extern bool is_migrant(struct unit *u); extern int study_cost(struct unit *u, skill_t talent); -#define MAXTEACHERS 4 +#define MAXTEACHERS 16 typedef struct teaching_info { struct unit *teachers[MAXTEACHERS]; int value; diff --git a/src/summary.c b/src/summary.c index 92405db33..cd6e912e0 100644 --- a/src/summary.c +++ b/src/summary.c @@ -1,4 +1,4 @@ -/* +/* * +-------------------+ Christian Schlittchen * | | Enno Rehling * | Eressea PBEM host | Katja Zedel diff --git a/src/test_eressea.c b/src/test_eressea.c index ccbac8463..b5a2e2a42 100644 --- a/src/test_eressea.c +++ b/src/test_eressea.c @@ -54,6 +54,8 @@ int RunAllTests(void) RUN_TESTS(suite, unicode); RUN_TESTS(suite, strings); RUN_TESTS(suite, rng); + /* items */ + RUN_TESTS(suite, xerewards); /* kernel */ RUN_TESTS(suite, alliance); RUN_TESTS(suite, unit); @@ -71,6 +73,8 @@ int RunAllTests(void) RUN_TESTS(suite, spellbook); RUN_TESTS(suite, building); RUN_TESTS(suite, spell); + RUN_TESTS(suite, spells); + RUN_TESTS(suite, magicresistance); RUN_TESTS(suite, ally); RUN_TESTS(suite, messages); /* gamecode */ @@ -84,6 +88,7 @@ int RunAllTests(void) RUN_TESTS(suite, upkeep); RUN_TESTS(suite, vortex); RUN_TESTS(suite, wormhole); + RUN_TESTS(suite, spy); printf("\ntest summary: %d tests, %d failed\n", suite->count, suite->failCount); log_flags = flags; diff --git a/src/tests.c b/src/tests.c index 597e7fbc8..9c03e1e18 100644 --- a/src/tests.c +++ b/src/tests.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -30,7 +31,7 @@ struct race *test_create_race(const char *name) { race *rc = rc_get_or_create(name); rc->maintenance = 10; - rc->ec_flags |= GETITEM | GIVEITEM; + rc->ec_flags |= GETITEM; return rc; } @@ -174,6 +175,11 @@ void test_create_world(void) itype->weight = 5000; itype->capacity = 7000; + itype = test_create_itemtype("cart"); + itype->flags |= ITF_BIG | ITF_VEHICLE; + itype->weight = 4000; + itype->capacity = 14000; + test_create_itemtype("iron"); test_create_itemtype("stone"); @@ -239,6 +245,7 @@ const message_type *register_msg(const char *type, int n_param, ...) { void assert_messages(struct CuTest * tc, struct mlist *msglist, const message_type **types, int num_msgs, bool exact_match, ...) { + char buf[100]; va_list args; int found = 0, argc = -1; struct message *msg; @@ -247,14 +254,15 @@ void assert_messages(struct CuTest * tc, struct mlist *msglist, const message_ty va_start(args, exact_match); while (msglist) { + msg = msglist->msg; if (found >= num_msgs) { if (exact_match) { - CuFail(tc, "too many messages"); + slprintf(buf, sizeof(buf), "too many messages: %s", msg->type->name); + CuFail(tc, buf); } else { break; } } - msg = msglist->msg; if (exact_match || match) argc = va_arg(args, int); @@ -271,3 +279,8 @@ void assert_messages(struct CuTest * tc, struct mlist *msglist, const message_ty va_end(args); } + +void disabled_test(void *suite, void (*test)(CuTest *), const char *name) { + (void)test; + fprintf(stderr, "%s: SKIP\n", name); +} diff --git a/src/tests.h b/src/tests.h index e517a6fb7..3da238fdc 100644 --- a/src/tests.h +++ b/src/tests.h @@ -47,6 +47,10 @@ extern "C" { void assert_messages(struct CuTest * tc, struct mlist *msglist, const struct message_type **types, int num_msgs, bool exact_match, ...); + void disabled_test(void *suite, void (*)(struct CuTest *), const char *name); + +#define DISABLE_TEST(SUITE, TEST) disabled_test(SUITE, TEST, #TEST) + #ifdef __cplusplus } #endif diff --git a/src/triggers/createcurse.c b/src/triggers/createcurse.c index eeff5eb51..07e8a370e 100644 --- a/src/triggers/createcurse.c +++ b/src/triggers/createcurse.c @@ -48,9 +48,9 @@ typedef struct createcurse_data { struct unit *mage; struct unit *target; const curse_type *type; - float vigour; + double vigour; int duration; - float effect; + double effect; int men; } createcurse_data; @@ -97,13 +97,15 @@ static int createcurse_read(trigger * t, struct storage *store) { createcurse_data *td = (createcurse_data *)t->data.v; char zText[128]; + float flt; read_reference(&td->mage, store, read_unit_reference, resolve_unit); read_reference(&td->target, store, read_unit_reference, resolve_unit); READ_TOK(store, zText, sizeof(zText)); td->type = ct_find(zText); - READ_FLT(store, &td->vigour); + READ_FLT(store, &flt); + td->vigour = flt; READ_INT(store, &td->duration); if (global.data_version < CURSEFLOAT_VERSION) { int n; @@ -111,7 +113,8 @@ static int createcurse_read(trigger * t, struct storage *store) td->effect = (float)n; } else { - READ_FLT(store, &td->effect); + READ_FLT(store, &flt); + td->effect = flt; } READ_INT(store, &td->men); return AT_READ_OK; @@ -127,7 +130,7 @@ trigger_type tt_createcurse = { }; trigger *trigger_createcurse(struct unit * mage, struct unit * target, - const curse_type * ct, float vigour, int duration, float effect, int men) + const curse_type * ct, double vigour, int duration, double effect, int men) { trigger *t = t_new(&tt_createcurse); createcurse_data *td = (createcurse_data *)t->data.v; diff --git a/src/triggers/createcurse.h b/src/triggers/createcurse.h index 9798e753a..c3602ec6a 100644 --- a/src/triggers/createcurse.h +++ b/src/triggers/createcurse.h @@ -33,8 +33,8 @@ extern "C" { extern struct trigger_type tt_createcurse; struct trigger *trigger_createcurse(struct unit *mage, - struct unit *target, const struct curse_type *ct, float vigour, - int duration, float effect, int men); + struct unit *target, const struct curse_type *ct, double vigour, + int duration, double effect, int men); #ifdef __cplusplus } diff --git a/src/upkeep.c b/src/upkeep.c index 5eecc1b42..d1c34f476 100644 --- a/src/upkeep.c +++ b/src/upkeep.c @@ -42,9 +42,7 @@ int lifestyle(const unit * u) static bool help_money(const unit * u) { - if (u_race(u)->ec_flags & GIVEITEM) - return true; - return false; + return !(u_race(u)->ec_flags & ECF_KEEP_ITEM); } static void help_feed(unit * donor, unit * u, int *need_p) diff --git a/src/upkeep.test.c b/src/upkeep.test.c index c7757624a..46d9a6d04 100644 --- a/src/upkeep.test.c +++ b/src/upkeep.test.c @@ -1,4 +1,4 @@ -#include +#include #include "upkeep.h" #include @@ -82,6 +82,7 @@ void test_upkeep_from_pool(CuTest * tc) assert(i_silver); r = findregion(0, 0); u1 = test_create_unit(test_create_faction(test_create_race("human")), r); + assert(u1); u2 = test_create_unit(u1->faction, r); assert(r && u1 && u2); diff --git a/src/util/attrib.c b/src/util/attrib.c index dd1120b5c..fb50d8dfc 100644 --- a/src/util/attrib.c +++ b/src/util/attrib.c @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 1998-2015, Enno Rehling Katja Zedel @@ -39,7 +39,7 @@ static unsigned int __at_hashkey(const char *s) while (i > 0) { key = (s[--i] + key * 37); } - return key & 0x7fffffff; + return key & 0x7fffffff; //TODO: V112 http://www.viva64.com/en/V112 Dangerous magic number 0x7fffffff used: return key & 0x7fffffff;. } void at_register(attrib_type * at) @@ -47,7 +47,7 @@ void at_register(attrib_type * at) attrib_type *find; if (at->read == NULL) { - log_warning("registering non-persistent attribute %s.\n", at->name); + log_warning("registering non-persistent attribute %s.\n", at->name); //TODO: V111 http://www.viva64.com/en/V111 Call of function 'log_warning' with variable number of arguments. Second argument has memsize type. } at->hashkey = __at_hashkey(at->name); find = at_hash[at->hashkey % MAXATHASH]; @@ -55,7 +55,7 @@ void at_register(attrib_type * at) find = find->nexthash; } if (find && find == at) { - log_warning("attribute '%s' was registered more than once\n", at->name); + log_warning("attribute '%s' was registered more than once\n", at->name); //TODO: V111 http://www.viva64.com/en/V111 Call of function 'log_warning' with variable number of arguments. Second argument has memsize type. return; } else { @@ -69,7 +69,7 @@ static attrib_type *at_find(unsigned int hk) { const char *translate[3][2] = { { "zielregion", "targetregion" }, /* remapping: from 'zielregion, heute targetregion */ - { "verzaubert", "curse" }, /* remapping: frher verzaubert, jetzt curse */ + { "verzaubert", "curse" }, /* remapping: früher verzaubert, jetzt curse */ { NULL, NULL } }; attrib_type *find = at_hash[hk % MAXATHASH]; @@ -110,11 +110,11 @@ const attrib *a_findc(const attrib * a, const attrib_type * at) static attrib *a_insert(attrib * head, attrib * a) { - attrib **pa = &head->next; - + attrib **pa; assert(!(a->type->flags & ATF_UNIQUE)); assert(head && head->type == a->type); + pa = &head->next; while (*pa && (*pa)->type == a->type) { pa = &(*pa)->next; } @@ -250,7 +250,7 @@ int a_age(attrib ** p) { attrib **ap = p; /* Attribute altern, und die Entfernung (age()==0) eines Attributs - * hat Einflu auf den Besitzer */ + * hat Einfluß auf den Besitzer */ while (*ap) { attrib *a = *ap; if (a->type->age) { @@ -299,7 +299,7 @@ int a_read(struct storage *store, attrib ** attribs, void *owner) na = a_new(at); } else { - const void * kv = 0; + void * kv = 0; cb_find_prefix(&cb_deprecated, zText, strlen(zText) + 1, &kv, 1, 0); if (kv) { cb_get_kv(kv, &reader, sizeof(reader)); diff --git a/src/util/attrib.h b/src/util/attrib.h index 11bc92bd1..cbba4ebf4 100644 --- a/src/util/attrib.h +++ b/src/util/attrib.h @@ -30,14 +30,14 @@ extern "C" { typedef struct attrib { const struct attrib_type *type; union { - afun f; - void *v; + afun f; //TODO: V117 http://www.viva64.com/en/V117 Memsize type is used in the union. + void *v; //TODO: V117 http://www.viva64.com/en/V117 Memsize type is used in the union. int i; float flt; char c; short s; short sa[2]; - char ca[4]; + char ca[4]; //TODO: V112 http://www.viva64.com/en/V112 Dangerous magic number 4 used: char ca[4];. } data; /* internal data, do not modify: */ struct attrib *next; /* next attribute in the list */ @@ -90,8 +90,8 @@ extern "C" { #define AT_READ_OK 0 #define AT_READ_FAIL -1 -#define AT_AGE_REMOVE 0 /* remove the attribute after calling age() */ -#define AT_AGE_KEEP 1 /* keep the attribute for another turn */ +#define AT_AGE_KEEP 0 /* keep the attribute for another turn */ +#define AT_AGE_REMOVE 1 /* remove the attribute after calling age() */ #ifdef __cplusplus } diff --git a/src/util/bsdstring.c b/src/util/bsdstring.c index f1694eed6..5ec87bfa1 100644 --- a/src/util/bsdstring.c +++ b/src/util/bsdstring.c @@ -7,16 +7,12 @@ #include "bsdstring.h" -int wrptr(char **ptr, size_t * size, int bytes) +int wrptr(char **ptr, size_t * size, size_t bytes) { if (bytes == 0) { return 0; } - if (bytes < 0) { - *size = 0; - return EINVAL; - } - if (bytes <= *(int *)size) { + if (bytes <= *size) { *ptr += bytes; *size -= bytes; return 0; @@ -24,7 +20,7 @@ int wrptr(char **ptr, size_t * size, int bytes) *ptr += *size; *size = 0; - return ENAMETOOLONG; + return ERANGE; } #ifndef HAVE_STRLCPY @@ -35,6 +31,7 @@ size_t strlcpy(char *dst, const char *src, size_t siz) register const char *s = src; register size_t n = siz; + assert(src && dst); /* Copy as many bytes as will fit */ if (n != 0 && --n != 0) { do { diff --git a/src/util/bsdstring.h b/src/util/bsdstring.h index 91b89465d..883e102e6 100644 --- a/src/util/bsdstring.h +++ b/src/util/bsdstring.h @@ -2,7 +2,7 @@ #define UTIL_BSDSTRING_H #include -extern int wrptr(char **ptr, size_t * size, int bytes); +extern int wrptr(char **ptr, size_t * size, size_t bytes); #ifndef HAVE_STRLCPY extern size_t strlcpy(char *dst, const char *src, size_t siz); @@ -17,5 +17,6 @@ extern size_t slprintf(char * dst, size_t size, const char * format, ...); #endif #define WARN_STATIC_BUFFER() log_warning("static buffer too small in %s:%d\n", __FILE__, __LINE__) +#define INFO_STATIC_BUFFER() log_info("static buffer too small in %s:%d\n", __FILE__, __LINE__) #endif diff --git a/src/util/bsdstring.test.c b/src/util/bsdstring.test.c index f7ac97dd3..6fcb86515 100644 --- a/src/util/bsdstring.test.c +++ b/src/util/bsdstring.test.c @@ -9,15 +9,15 @@ static void test_strlcat(CuTest * tc) memset(buffer, 0x7f, sizeof(buffer)); buffer[0] = '\0'; - CuAssertIntEquals(tc, 4, strlcat(buffer, "herp", 4)); + CuAssertIntEquals(tc, 4, (int)strlcat(buffer, "herp", 4)); CuAssertStrEquals(tc, "her", buffer); buffer[0] = '\0'; - CuAssertIntEquals(tc, 4, strlcat(buffer, "herp", 8)); + CuAssertIntEquals(tc, 4, (int)strlcat(buffer, "herp", 8)); CuAssertStrEquals(tc, "herp", buffer); CuAssertIntEquals(tc, 0x7f, buffer[5]); - CuAssertIntEquals(tc, 8, strlcat(buffer, "derp", 8)); + CuAssertIntEquals(tc, 8, (int)strlcat(buffer, "derp", 8)); CuAssertStrEquals(tc, "herpder", buffer); CuAssertIntEquals(tc, 0x7f, buffer[8]); } @@ -28,14 +28,14 @@ static void test_strlcpy(CuTest * tc) memset(buffer, 0x7f, sizeof(buffer)); - CuAssertIntEquals(tc, 4, strlcpy(buffer, "herp", 4)); + CuAssertIntEquals(tc, 4, (int)strlcpy(buffer, "herp", 4)); CuAssertStrEquals(tc, "her", buffer); - CuAssertIntEquals(tc, 4, strlcpy(buffer, "herp", 8)); + CuAssertIntEquals(tc, 4, (int)strlcpy(buffer, "herp", 8)); CuAssertStrEquals(tc, "herp", buffer); CuAssertIntEquals(tc, 0x7f, buffer[5]); - CuAssertIntEquals(tc, 8, strlcpy(buffer, "herpderp", 8)); + CuAssertIntEquals(tc, 8, (int)strlcpy(buffer, "herpderp", 8)); CuAssertStrEquals(tc, "herpder", buffer); CuAssertIntEquals(tc, 0x7f, buffer[8]); } @@ -49,11 +49,11 @@ static void test_slprintf(CuTest * tc) CuAssertTrue(tc, slprintf(buffer, 4, "%s", "herpderp") > 3); CuAssertStrEquals(tc, "her", buffer); - CuAssertIntEquals(tc, 4, slprintf(buffer, 8, "%s", "herp")); + CuAssertIntEquals(tc, 4, (int)slprintf(buffer, 8, "%s", "herp")); CuAssertStrEquals(tc, "herp", buffer); CuAssertIntEquals(tc, 0x7f, buffer[5]); - CuAssertIntEquals(tc, 8, slprintf(buffer, 8, "%s", "herpderp")); + CuAssertIntEquals(tc, 8, (int)slprintf(buffer, 8, "%s", "herpderp")); CuAssertStrEquals(tc, "herpder", buffer); CuAssertIntEquals(tc, 0x7f, buffer[8]); } diff --git a/src/util/crmessage.c b/src/util/crmessage.c index 517adfd6e..942ba2610 100644 --- a/src/util/crmessage.c +++ b/src/util/crmessage.c @@ -15,7 +15,7 @@ #include "crmessage.h" #include "message.h" -#include "goodies.h" +#include "strings.h" #include "log.h" #include diff --git a/src/util/functions.c b/src/util/functions.c index 8b999695e..9d0afb63d 100644 --- a/src/util/functions.c +++ b/src/util/functions.c @@ -30,7 +30,7 @@ static critbit_tree cb_functions; pf_generic get_function(const char *name) { - const void * matches; + void * matches; pf_generic result; if (cb_find_prefix(&cb_functions, name, strlen(name) + 1, &matches, 1, 0)) { cb_get_kv(matches, &result, sizeof(result)); diff --git a/src/util/goodies.c b/src/util/goodies.c index b46f9cb7a..2444d0f47 100644 --- a/src/util/goodies.c +++ b/src/util/goodies.c @@ -19,10 +19,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include "goodies.h" -#include "unicode.h" - /* libc includes */ -#include #include #include @@ -53,23 +50,6 @@ int *intlist_find(int *i_p, int fi) return NULL; } -char *set_string(char **s, const char *neu) -{ - if (neu == NULL) { - free(*s); - *s = NULL; - } - else if (*s == NULL) { - *s = malloc(strlen(neu) + 1); - strcpy(*s, neu); - } - else { - *s = realloc(*s, strlen(neu) + 1); - strcpy(*s, neu); - } - return *s; -} - static int spc_email_isvalid(const char *address) { int count = 0; diff --git a/src/util/goodies.h b/src/util/goodies.h index 045a23019..c619c4958 100644 --- a/src/util/goodies.h +++ b/src/util/goodies.h @@ -18,40 +18,16 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #ifndef GOODIES_H #define GOODIES_H + #ifdef __cplusplus extern "C" { #endif - extern char *set_string(char **s, const char *neu); - extern int set_email(char **pemail, const char *newmail); + int set_email(char **pemail, const char *newmail); - extern int *intlist_init(void); - extern int *intlist_add(int *i_p, int i); - extern int *intlist_find(int *i_p, int i); - - extern unsigned int hashstring(const char *s); - extern const char *escape_string(const char *str, char *buffer, - unsigned int len); - extern unsigned int jenkins_hash(unsigned int a); - extern unsigned int wang_hash(unsigned int a); - - /* benchmark for units: - * JENKINS_HASH: 5.25 misses/hit (with good cache behavior) - * WANG_HASH: 5.33 misses/hit (with good cache behavior) - * KNUTH_HASH: 1.93 misses/hit (with bad cache behavior) - * CF_HASH: fucking awful! - */ -#define KNUTH_HASH1(a, m) ((a) % m) -#define KNUTH_HASH2(a, m) (m - 2 - a % (m-2)) -#define CF_HASH1(a, m) ((a) % m) -#define CF_HASH2(a, m) (8 - ((a) & 7)) -#define JENKINS_HASH1(a, m) (jenkins_hash(a) % m) -#define JENKINS_HASH2(a, m) 1 -#define WANG_HASH1(a, m) (wang_hash(a) % m) -#define WANG_HASH2(a, m) 1 - -#define HASH1 JENKINS_HASH1 -#define HASH2 JENKINS_HASH2 + int *intlist_init(void); + int *intlist_add(int *i_p, int i); + int *intlist_find(int *i_p, int i); #ifdef __cplusplus } diff --git a/src/util/language.c b/src/util/language.c index 677832636..9409ab3c7 100644 --- a/src/util/language.c +++ b/src/util/language.c @@ -21,7 +21,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "language_struct.h" #include "log.h" -#include "goodies.h" +#include "strings.h" #include "umlaut.h" #include @@ -153,8 +153,13 @@ const char *locale_string(const locale * lang, const char *key, bool warn) if (warn) { log_warning("missing translation for \"%s\" in locale %s\n", key, lang->name); } - if (lang->fallback) { - return locale_string(lang->fallback, key, warn); + if (default_locale && lang != default_locale) { + const char * value = locale_string(default_locale, key, warn); + if (value) { + /* TODO: evil side-effects for a const function */ + locale_setstring(get_or_create_locale(lang->name), key, value); + } + return value; } } return 0; diff --git a/src/util/language_struct.h b/src/util/language_struct.h index 84932532e..7caad74af 100644 --- a/src/util/language_struct.h +++ b/src/util/language_struct.h @@ -19,7 +19,6 @@ typedef struct locale { struct locale *next; unsigned int hashkey; struct locale_str *strings[SMAXHASH]; - struct locale *fallback; } locale; extern locale *default_locale; diff --git a/src/util/log.c b/src/util/log.c index d67fd6775..fadcb532a 100644 --- a/src/util/log.c +++ b/src/util/log.c @@ -1,4 +1,4 @@ -/* +/* +-------------------+ Christian Schlittchen | | Enno Rehling | Eressea PBEM host | Katja Zedel @@ -54,13 +54,13 @@ cp_convert(const char *format, char *buffer, size_t length, int codepage) char *pos = buffer; while (pos + 1 < buffer + length && *input) { - size_t length = 0; + size_t size = 0; int result = 0; if (codepage == 437) { - result = unicode_utf8_to_cp437(pos, input, &length); + result = unicode_utf8_to_cp437(pos, input, &size); } else if (codepage == 1252) { - result = unicode_utf8_to_cp1252(pos, input, &length); + result = unicode_utf8_to_cp1252(pos, input, &size); } if (result != 0) { *pos = 0; /* just in case caller ignores our return value */ @@ -264,6 +264,34 @@ void log_error(const char *format, ...) } } +void log_fatal(const char *format, ...) +{ + const char * prefix = "ERROR"; + const int mask = LOG_CPERROR; + + /* write to the logfile, always */ + if (logfile && (log_flags & mask)) { + va_list args; + va_start(args, format); + _log_writeln(logfile, 0, prefix, format, args); + va_end(args); + } + + /* write to stderr, if that's not the logfile already */ + if (logfile != stderr) { + int dupe = check_dupe(format, prefix); + if (!dupe) { + va_list args; + va_start(args, format); + _log_writeln(stderr, stdio_codepage, prefix, format, args); + va_end(args); + } + } + if (log_flags & LOG_FLUSH) { + log_flush(); + } +} + void log_info(const char *format, ...) { const char * prefix = "INFO"; diff --git a/src/util/log.h b/src/util/log.h index 1e56d4b34..ef93ca3a5 100644 --- a/src/util/log.h +++ b/src/util/log.h @@ -20,8 +20,9 @@ extern "C" { extern void log_flush(void); /* use macros above instead of these: */ - extern void log_warning(const char *format, ...); + extern void log_fatal(const char *format, ...); extern void log_error(const char *format, ...); + extern void log_warning(const char *format, ...); extern void log_debug(const char *format, ...); extern void log_info(const char *format, ...); extern void log_printf(FILE * ios, const char *format, ...); diff --git a/src/util/message.c b/src/util/message.c index 302e8d57c..b082d9d98 100644 --- a/src/util/message.c +++ b/src/util/message.c @@ -14,7 +14,7 @@ #include #include "message.h" -#include "goodies.h" +#include "strings.h" #include "log.h" #include "quicklist.h" diff --git a/src/util/nrmessage.c b/src/util/nrmessage.c index 5543b87ef..640cb81e6 100644 --- a/src/util/nrmessage.c +++ b/src/util/nrmessage.c @@ -21,7 +21,7 @@ #include "message.h" #include "language.h" #include "translation.h" -#include "goodies.h" +#include "strings.h" /* libc includes */ #include diff --git a/src/util/rng.h b/src/util/rng.h index 2e8e5affb..1cc95d094 100644 --- a/src/util/rng.h +++ b/src/util/rng.h @@ -29,7 +29,8 @@ extern "C" { long genrand_int31(void); # define rng_init(seed) init_genrand(seed) -# define rng_int genrand_int31 +# define rng_int (int)genrand_int31 +# define rng_uint (unsigned int)genrand_int32 # define rng_double genrand_real2 # define RNG_RAND_MAX 0x7fffffff #else diff --git a/src/util/strings.c b/src/util/strings.c index 948044532..b3801d52f 100644 --- a/src/util/strings.c +++ b/src/util/strings.c @@ -21,10 +21,29 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. /* libc includes */ #include #include +#include + +char *set_string(char **s, const char *neu) +{ + if (neu == NULL) { + free(*s); + *s = NULL; + } + else if (*s == NULL) { + *s = malloc(strlen(neu) + 1); + strcpy(*s, neu); + } + else { + *s = realloc(*s, strlen(neu) + 1); + strcpy(*s, neu); + } + return *s; +} unsigned int hashstring(const char *s) { unsigned int key = 0; + assert(s); while (*s) { key = key * 37 + *s++; } @@ -32,7 +51,7 @@ unsigned int hashstring(const char *s) } const char *escape_string(const char *str, char *buffer, - unsigned int len) + size_t len) { const char *start = strchr(str, '\"'); if (!start) start = strchr(str, '\\'); diff --git a/src/util/strings.h b/src/util/strings.h new file mode 100644 index 000000000..7178cf179 --- /dev/null +++ b/src/util/strings.h @@ -0,0 +1,52 @@ +/* +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 STRINGS_H +#define STRINGS_H +#ifdef __cplusplus +extern "C" { +#endif + + char *set_string(char **s, const char *neu); + unsigned int hashstring(const char *s); + const char *escape_string(const char *str, char *buffer, size_t len); + unsigned int jenkins_hash(unsigned int a); + unsigned int wang_hash(unsigned int a); + + /* benchmark for units: + * JENKINS_HASH: 5.25 misses/hit (with good cache behavior) + * WANG_HASH: 5.33 misses/hit (with good cache behavior) + * KNUTH_HASH: 1.93 misses/hit (with bad cache behavior) + * CF_HASH: fucking awful! + */ +#define KNUTH_HASH1(a, m) ((a) % m) +#define KNUTH_HASH2(a, m) (m - 2 - a % (m-2)) +#define CF_HASH1(a, m) ((a) % m) +#define CF_HASH2(a, m) (8 - ((a) & 7)) +#define JENKINS_HASH1(a, m) (jenkins_hash(a) % m) +#define JENKINS_HASH2(a, m) 1 +#define WANG_HASH1(a, m) (wang_hash(a) % m) +#define WANG_HASH2(a, m) 1 + +#define HASH1 JENKINS_HASH1 +#define HASH2 JENKINS_HASH2 + +#ifdef __cplusplus +} +#endif +#endif /* STRINGS_H */ diff --git a/src/util/strings.test.c b/src/util/strings.test.c index c8dd63147..bcee29e47 100644 --- a/src/util/strings.test.c +++ b/src/util/strings.test.c @@ -2,7 +2,7 @@ #include #include #include -#include "goodies.h" +#include "strings.h" static void test_escape_string(CuTest * tc) { diff --git a/src/util/translation.c b/src/util/translation.c index 804aaf4c0..16d3e684f 100644 --- a/src/util/translation.c +++ b/src/util/translation.c @@ -31,7 +31,7 @@ typedef struct opstack { variant *begin; variant *top; - int size; + unsigned int size; } opstack; variant opstack_pop(opstack ** stackp) @@ -53,10 +53,16 @@ void opstack_push(opstack ** stackp, variant data) stack->top = stack->begin; *stackp = stack; } - if (stack->top - stack->begin == stack->size) { + if (stack->top == stack->begin + stack->size) { size_t pos = stack->top - stack->begin; + void *tmp; stack->size += stack->size; - stack->begin = realloc(stack->begin, sizeof(variant) * stack->size); + tmp = realloc(stack->begin, sizeof(variant) * stack->size); + if (!tmp) { + log_error("realloc out of memory"); + abort(); + } + stack->begin = (variant *)tmp; stack->top = stack->begin + pos; } *stack->top++ = data; @@ -66,7 +72,7 @@ void opstack_push(opstack ** stackp, variant data) ** static buffer malloc **/ -#define BBUFSIZE 128*1024 +#define BBUFSIZE 0x20000 static struct { char *begin; char *end; @@ -79,7 +85,7 @@ char *balloc(size_t size) static int init = 0; /* STATIC_XCALL: used across calls */ if (!init) { init = 1; - buffer.current = buffer.begin = malloc(BBUFSIZE); + buffer.current = buffer.begin = malloc(BBUFSIZE * sizeof(char)); buffer.end = buffer.begin + BBUFSIZE; } if (buffer.current + size > buffer.end) { @@ -168,7 +174,7 @@ void add_function(const char *symbol, evalfun parse) static evalfun find_function(const char *symbol) { - const void * matches; + void * matches; if (cb_find_prefix(&functions, symbol, strlen(symbol) + 1, &matches, 1, 0)) { evalfun result; cb_get_kv(matches, &result, sizeof(result)); @@ -269,7 +275,7 @@ static const char *parse_string(opstack ** stack, const char *in, } else { int ch = (unsigned char)(*ic); - int bytes; + size_t bytes; switch (ch) { case '\\': @@ -285,8 +291,8 @@ static const char *parse_string(opstack ** stack, const char *in, if (ic == NULL) return NULL; c = (char *)opop_v(stack); - bytes = (int)(c ? strlcpy(oc, c, size) : 0); - if (bytes < (int)size) + bytes = (c ? strlcpy(oc, c, size) : 0); + if (bytes < size) oc += bytes; else oc += size; @@ -363,7 +369,7 @@ static const char *parse(opstack ** stack, const char *inn, const char *translate(const char *format, const void *userdata, const char *vars, variant args[]) { - int i = 0; + unsigned int i = 0; const char *ic = vars; char symbol[32]; char *oc = symbol; diff --git a/src/util/unicode.c b/src/util/unicode.c index 2a369ae1e..4be39a551 100644 --- a/src/util/unicode.c +++ b/src/util/unicode.c @@ -84,7 +84,7 @@ size_t * inlen) if (op - out >= os - 1) break; *op++ = 0xC3; - *op++ = c - 64; + *op++ = (unsigned char)(c - 64); } else if (c > 0x7F) { if (op - out >= os - 1) diff --git a/src/util/variant.h b/src/util/variant.h index b65ee0868..4559264ed 100644 --- a/src/util/variant.h +++ b/src/util/variant.h @@ -5,12 +5,12 @@ extern "C" { #endif typedef union variant { - void *v; + void *v; //TODO: V117 http://www.viva64.com/en/V117 Memsize type is used in the union. int i; char c; short s; short sa[2]; - char ca[4]; + char ca[4]; //TODO: V112 http://www.viva64.com/en/V112 Dangerous magic number 4 used: char ca[4];. float f; } variant; diff --git a/storage b/storage index bcc2874cf..2bcd3b1e6 160000 --- a/storage +++ b/storage @@ -1 +1 @@ -Subproject commit bcc2874cf289a1d0fc9cc79ff3ed271403b2e24c +Subproject commit 2bcd3b1e64764321773672333bd133a61b35b840 diff --git a/tests/data/184.dat b/tests/data/184.dat new file mode 100644 index 000000000..74d72258a Binary files /dev/null and b/tests/data/184.dat differ diff --git a/tests/eressea.ini b/tests/eressea.ini new file mode 100644 index 000000000..e84171d45 --- /dev/null +++ b/tests/eressea.ini @@ -0,0 +1,14 @@ +[eressea] +base = . +report = reports +verbose = 0 +lomem = 0 +debug = 0 +memcheck = 0 +locales = de,en + +[lua] +install = .. +paths = lunit:scripts +maxnmrs = 20 +rules = e2 diff --git a/tests/orders.184 b/tests/orders.184 new file mode 100644 index 000000000..e69de29bb