summaryrefslogtreecommitdiff
path: root/plugins/seedwatch.cpp
diff options
context:
space:
mode:
authorPetr Mrázek2011-10-30 02:52:25 +0100
committerPetr Mrázek2011-10-30 02:52:25 +0100
commita3a16295217afea8b7c4c3894e44051441d82095 (patch)
treec43e991995f5f51f59b338b5181ab91f2bf21469 /plugins/seedwatch.cpp
parent13ca2e608fb478ad1226281a1397091e90e55e20 (diff)
downloaddfhack-a3a16295217afea8b7c4c3894e44051441d82095.tar.gz
dfhack-a3a16295217afea8b7c4c3894e44051441d82095.tar.bz2
dfhack-a3a16295217afea8b7c4c3894e44051441d82095.tar.xz
Fix seedwatch some more.
Diffstat (limited to 'plugins/seedwatch.cpp')
-rwxr-xr-xplugins/seedwatch.cpp348
1 files changed, 91 insertions, 257 deletions
diff --git a/plugins/seedwatch.cpp b/plugins/seedwatch.cpp
index 523bbc09..9f8afae0 100755
--- a/plugins/seedwatch.cpp
+++ b/plugins/seedwatch.cpp
@@ -9,23 +9,20 @@
#include "dfhack/Export.h"
#include "dfhack/PluginManager.h"
#include "dfhack/Process.h"
-#include "dfhack/modules/Items.h"
#include "dfhack/modules/Materials.h"
+#include "dfhack/modules/Items.h"
+#include "dfhack/modules/World.h"
+#include "dfhack/modules/kitchen.h"
+#include <dfhack/VersionInfo.h>
-typedef int32_t t_materialIndex;
-typedef int16_t t_material, t_itemType, t_itemSubtype;
-typedef int8_t t_exclusionType;
+using DFHack::t_materialType;
+using DFHack::t_materialIndex;
-const unsigned int seedLimit = 400; // a limit on the limits which can be placed on seeds
-const t_itemSubtype organicSubtype = -1; // seems to fixed
-const t_exclusionType cookingExclusion = 1; // seems to be fixed
-const t_itemType limitType = 0; // used to store limit as an entry in the exclusion list. 0 = BAR
-const t_itemSubtype limitSubtype = 0; // used to store limit as an entry in the exclusion list
-const t_exclusionType limitExclusion = 4; // used to store limit as an entry in the exclusion list
const int buffer = 20; // seed number buffer - 20 is reasonable
bool running = false; // whether seedwatch is counting the seeds or not
-std::map<std::string, std::string> abbreviations; // abbreviations for the standard plants
+// abbreviations for the standard plants
+std::map<std::string, std::string> abbreviations;
bool ignoreSeeds(DFHack::t_itemflags& f) // seeds with the following flags should not be counted
{
@@ -41,47 +38,26 @@ bool ignoreSeeds(DFHack::t_itemflags& f) // seeds with the following flags shoul
f.in_building ||
f.in_job;
};
-void updateCountAndSubindices(DFHack::Core& core, std::map<t_materialIndex, unsigned int>& seedCount, std::map<t_materialIndex, t_material>& seedSubindices, std::map<t_materialIndex, t_material>& plantSubindices) // fills seedCount, seedSubindices and plantSubindices
-{
- DFHack::Items& itemsModule = *core.getItems();
- itemsModule.Start();
- std::vector<DFHack::df_item*> items;
- itemsModule.readItemVector(items);
-
- DFHack::df_item * item;
- std::size_t size = items.size();
- for(std::size_t i = 0; i < size; ++i)
- {
- item = items[i];
- t_materialIndex materialIndex = item->getMaterialIndex();
- switch(item->getType())
- {
- case DFHack::Items::SEEDS:
- seedSubindices[materialIndex] = item->getMaterial();
- if(!ignoreSeeds(item->flags)) ++seedCount[materialIndex];
- break;
- case DFHack::Items::PLANT:
- plantSubindices[materialIndex] = item->getMaterial();
- break;
- }
- }
- itemsModule.Finish();
-};
void printHelp(DFHack::Core& core) // prints help
{
core.con.print(
- "Watches the numbers of plants and seeds available and enables/disables cooking automatically.\n"
+ "Watches the numbers of seeds available and enables/disables seed and plant cooking.\n"
"Each plant type can be assigned a limit. If their number falls below,\n"
"the plants and seeds of that type will be excluded from cookery.\n"
- "If the number rises above the limit + %i, then cooking will be allowed.\n"
+ "If the number rises above the limit + %i, then cooking will be allowed.\n", buffer
+ );
+ core.con.printerr(
+ "The plugin needs a fortress to be loaded and will deactivate automatically otherwise.\n"
+ "You have to reactivate with 'seedwatch start' after you load the game.\n"
+ );
+ core.con.print(
"Options:\n"
"seedwatch all - Adds all plants from the abbreviation list to the watch list.\n"
"seedwatch start - Start watching.\n"
"seedwatch stop - Stop watching.\n"
"seedwatch info - Display whether seedwatch is watching, and the watch list.\n"
"seedwatch clear - Clears the watch list.\n\n"
- , buffer
);
if(!abbreviations.empty())
{
@@ -117,209 +93,6 @@ std::string searchAbbreviations(std::string in)
}
};
-// helps to organise access to the cooking exclusions
-class t_kitchenExclusions
-{
-public:
- t_kitchenExclusions(DFHack::Core& core_) // constructor
- : core(core_)
- , itemTypes (*((std::vector<t_itemType >*)(addr(core_,0))))
- , itemSubtypes (*((std::vector<t_itemSubtype >*)(addr(core_,1))))
- , materials (*((std::vector<t_material >*)(addr(core_,2))))
- , materialIndices (*((std::vector<t_materialIndex>*)(addr(core_,3))))
- , exclusionTypes (*((std::vector<t_exclusionType>*)(addr(core_,4))))
- {
- };
- void print() // print the exclusion list, with the material index also translated into its token (for organics) - for debug really
- {
- core.con.print("Kitchen Exclusions\n");
- DFHack::Materials& materialsModule= *core.getMaterials();
- materialsModule.ReadOrganicMaterials();
- for(std::size_t i = 0; i < size(); ++i)
- {
- core.con.print("%2u: IT:%2i IS:%i MI:%2i MS:%3i ET:%i %s\n", i, itemTypes[i], itemSubtypes[i], materialIndices[i], materials[i], exclusionTypes[i], materialsModule.organic[materialIndices[i]].id.c_str());
- }
- core.con.print("\n");
- };
- void allowCookery(t_materialIndex materialIndex) // remove this material from the exclusion list if it is in it
- {
- bool match = false;
- do
- {
- match = false;
- std::size_t matchIndex = 0;
- for(std::size_t i = 0; i < size(); ++i)
- {
- if(materialIndices[i] == materialIndex
- && (itemTypes[i] == DFHack::Items::SEEDS || itemTypes[i] == DFHack::Items::PLANT)
- && exclusionTypes[i] == cookingExclusion
- )
- {
- match = true;
- matchIndex = i;
- }
- }
- if(match)
- {
- itemTypes.erase(itemTypes.begin() + matchIndex);
- itemSubtypes.erase(itemSubtypes.begin() + matchIndex);
- materialIndices.erase(materialIndices.begin() + matchIndex);
- materials.erase( materials.begin() + matchIndex);
- exclusionTypes.erase(exclusionTypes.begin() + matchIndex);
- }
- } while(match);
- };
-
- // add this material to the exclusion list, if it is not already in it
- void denyCookery(t_materialIndex materialIndex, std::map<t_materialIndex, t_material>& seedMaterials, std::map<t_materialIndex, t_material>& plantMaterials)
- {
- if( seedMaterials.count(materialIndex) > 0)
- {
- bool alreadyIn = false;
- for(std::size_t i = 0; i < size(); ++i)
- {
- if(materialIndices[i] == materialIndex
- && itemTypes[i] == DFHack::Items::SEEDS
- && exclusionTypes[i] == cookingExclusion)
- {
- alreadyIn = true;
- }
- }
- if(!alreadyIn)
- {
- itemTypes.push_back(DFHack::Items::SEEDS);
- itemSubtypes.push_back(organicSubtype);
- materials.push_back( seedMaterials[materialIndex]);
- materialIndices.push_back(materialIndex);
- exclusionTypes.push_back(cookingExclusion);
- }
- }
- if( plantMaterials.count(materialIndex) > 0)
- {
- bool alreadyIn = false;
- for(std::size_t i = 0; i < size(); ++i)
- {
- if(materialIndices[i] == materialIndex
- && itemTypes[i] == DFHack::Items::PLANT
- && exclusionTypes[i] == cookingExclusion)
- {
- alreadyIn = true;
- }
- }
- if(!alreadyIn)
- {
- itemTypes.push_back(DFHack::Items::PLANT);
- itemSubtypes.push_back(organicSubtype);
- materials.push_back(plantMaterials[materialIndex]);
- materialIndices.push_back(materialIndex);
- exclusionTypes.push_back(cookingExclusion);
- }
- }
- };
-
- // fills a map with info from the limit info storage entries in the exclusion list
- void fillWatchMap(std::map<t_materialIndex, unsigned int>& watchMap)
- {
- watchMap.clear();
- for(std::size_t i = 0; i < size(); ++i)
- {
- if(itemTypes[i] == limitType && itemSubtypes[i] == limitSubtype && exclusionTypes[i] == limitExclusion)
- {
- watchMap[materialIndices[i]] = (unsigned int) materials[i];
- }
- }
- };
-
- // removes a limit info storage entry from the exclusion list if it is in it
- void removeLimit(t_materialIndex materialIndex)
- {
- bool match = false;
- do
- {
- match = false;
- std::size_t matchIndex = 0;
- for(std::size_t i = 0; i < size(); ++i)
- {
- if(itemTypes[i] == limitType
- && itemSubtypes[i] == limitSubtype
- && materialIndices[i] == materialIndex
- && exclusionTypes[i] == limitExclusion)
- {
- match = true;
- matchIndex = i;
- }
- }
- if(match)
- {
- itemTypes.erase(itemTypes.begin() + matchIndex);
- itemSubtypes.erase(itemSubtypes.begin() + matchIndex);
- materials.erase(materials.begin() + matchIndex);
- materialIndices.erase(materialIndices.begin() + matchIndex);
- exclusionTypes.erase(exclusionTypes.begin() + matchIndex);
- }
- } while(match);
- };
- // add a limit info storage item to the exclusion list, or alters an existing one
- void setLimit(t_materialIndex materialIndex, unsigned int limit)
- {
- removeLimit(materialIndex);
- if(limit > seedLimit) limit = seedLimit;
-
- itemTypes.push_back(limitType);
- itemSubtypes.push_back(limitSubtype);
- materialIndices.push_back(materialIndex);
- materials.push_back((t_material) (limit < seedLimit) ? limit : seedLimit);
- exclusionTypes.push_back(limitExclusion);
- };
- void clearLimits() // clears all limit info storage items from the exclusion list
- {
- bool match = false;
- do
- {
- match = false;
- std::size_t matchIndex;
- for(std::size_t i = 0; i < size(); ++i)
- {
- if(itemTypes[i] == limitType
- && itemSubtypes[i] == limitSubtype
- && exclusionTypes[i] == limitExclusion)
- {
- match = true;
- matchIndex = i;
- }
- }
- if(match)
- {
- itemTypes.erase(itemTypes.begin() + matchIndex);
- itemSubtypes.erase(itemSubtypes.begin() + matchIndex);
- materialIndices.erase(materialIndices.begin() + matchIndex);
- materials.erase( materials.begin() + matchIndex);
- exclusionTypes.erase(exclusionTypes.begin() + matchIndex);
- }
- } while(match);
- };
-private:
- DFHack::Core& core;
- std::vector<t_itemType>& itemTypes; // the item types vector of the kitchen exclusion list
- std::vector<t_itemSubtype>& itemSubtypes; // the item subtype vector of the kitchen exclusion list
- std::vector<t_material>& materials; // the material subindex vector of the kitchen exclusion list
- std::vector<t_materialIndex>& materialIndices; // the material index vector of the kitchen exclusion list
- std::vector<t_exclusionType>& exclusionTypes; // the exclusion type vector of the kitchen excluions list
- std::size_t size() // the size of the exclusions vectors (they are all the same size - if not, there is a problem!)
- {
- return itemTypes.size();
- };
- //FIXME: ugly, ugly hack. Use memory.xml instead.
- static uint32_t addr(const DFHack::Core& core, int index)
- {
- #ifdef LINUX_BUILD
- return 0x93f2b00 + 0xC * index;
- #else
- return core.p->getBase() + 0x014F0BB4 - 0x400000 + 0x10 * index;
- #endif
- };
-};
-
DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vector<std::string>& parameters)
{
DFHack::Core& core = *pCore;
@@ -339,6 +112,19 @@ DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vect
materialsReverser[organics[i].id] = i;
}
+ DFHack::World *w = core.getWorld();
+ DFHack::t_gamemodes gm;
+ w->ReadGameMode(gm);// FIXME: check return value
+
+ // if game mode isn't fortress mode
+ if(gm.g_mode != DFHack::GAMEMODE_DWARF || gm.g_type != DFHack::GAMETYPE_DWARF_MAIN)
+ {
+ // just print the help
+ printHelp(core);
+ core.Resume();
+ return DFHack::CR_OK;
+ }
+
std::string par;
int limit;
switch(parameters.size())
@@ -362,7 +148,7 @@ DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vect
}
else if(par == "clear")
{
- t_kitchenExclusions kitchenExclusions(core);
+ DFHack::Kitchen::Exclusions kitchenExclusions(core);
kitchenExclusions.clearLimits();
core.con.print("seedwatch watchlist cleared\n");
}
@@ -377,7 +163,7 @@ DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vect
{
core.con.print("seedwatch is not supervising. Use 'seedwatch start' to start supervision.\n");
}
- t_kitchenExclusions kitchenExclusions(core);
+ DFHack::Kitchen::Exclusions kitchenExclusions(core);
std::map<t_materialIndex, unsigned int> watchMap;
kitchenExclusions.fillWatchMap(watchMap);
if(watchMap.empty())
@@ -395,17 +181,35 @@ DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vect
}
else if(par == "debug")
{
- t_kitchenExclusions kitchenExclusions(core);
+ DFHack::Kitchen::Exclusions kitchenExclusions(core);
std::map<t_materialIndex, unsigned int> watchMap;
kitchenExclusions.fillWatchMap(watchMap);
- kitchenExclusions.print();
+ kitchenExclusions.debug_print();
+ }
+ /*
+ else if(par == "dumpmaps")
+ {
+
+ core.con.print("Plants:\n");
+ for(auto i = plantMaterialTypes.begin(); i != plantMaterialTypes.end(); i++)
+ {
+ auto t = materialsModule.df_organic->at(i->first);
+ core.con.print("%s : %u %u\n", organics[i->first].id.c_str(), i->second, t->material_basic_mat);
+ }
+ core.con.print("Seeds:\n");
+ for(auto i = seedMaterialTypes.begin(); i != seedMaterialTypes.end(); i++)
+ {
+ auto t = materialsModule.df_organic->at(i->first);
+ core.con.print("%s : %u %u\n", organics[i->first].id.c_str(), i->second, t->material_seed);
+ }
}
+ */
else
{
std::string token = searchAbbreviations(par);
if(materialsReverser.count(token) > 0)
{
- t_kitchenExclusions kitchenExclusions(core);
+ DFHack::Kitchen::Exclusions kitchenExclusions(core);
kitchenExclusions.removeLimit(materialsReverser[token]);
core.con.print("%s is not being watched\n", token.c_str());
}
@@ -422,7 +226,7 @@ DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vect
{
for(std::map<std::string, std::string>::const_iterator i = abbreviations.begin(); i != abbreviations.end(); ++i)
{
- t_kitchenExclusions kitchenExclusions(core);
+ DFHack::Kitchen::Exclusions kitchenExclusions(core);
if(materialsReverser.count(i->second) > 0) kitchenExclusions.setLimit(materialsReverser[i->second], limit);
}
}
@@ -431,7 +235,7 @@ DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vect
std::string token = searchAbbreviations(parameters[0]);
if(materialsReverser.count(token) > 0)
{
- t_kitchenExclusions kitchenExclusions(core);
+ DFHack::Kitchen::Exclusions kitchenExclusions(core);
kitchenExclusions.setLimit(materialsReverser[token], limit);
core.con.print("%s is being watched.\n", token.c_str());
}
@@ -489,22 +293,52 @@ DFhackCExport DFHack::command_result plugin_onupdate(DFHack::Core* pCore)
if(running)
{
DFHack::Core& core = *pCore;
+ DFHack::World *w = core.getWorld();
+ DFHack::t_gamemodes gm;
+ w->ReadGameMode(gm);// FIXME: check return value
+ // if game mode isn't fortress mode
+ if(gm.g_mode != DFHack::GAMEMODE_DWARF || gm.g_type != DFHack::GAMETYPE_DWARF_MAIN)
+ {
+ // stop running.
+ running = false;
+ core.con.printerr("seedwatch deactivated due to game mode switch\n");
+ return DFHack::CR_OK;
+ }
+ // this is dwarf mode, continue
std::map<t_materialIndex, unsigned int> seedCount; // the number of seeds
- std::map<t_materialIndex, t_material> seedSubindices; // holds information needed to add entries to the cooking exclusions
- std::map<t_materialIndex, t_material> plantSubindices; // holds information need to add entries to the cooking exclusions
- updateCountAndSubindices(core, seedCount, seedSubindices, plantSubindices);
- t_kitchenExclusions kitchenExclusions(core);
+ DFHack::Items& itemsModule = *core.getItems();
+ itemsModule.Start();
+ std::vector<DFHack::df_item*> items;
+ itemsModule.readItemVector(items);
+ DFHack::df_item * item;
+ // count all seeds and plants by RAW material
+ for(std::size_t i = 0; i < items.size(); ++i)
+ {
+ item = items[i];
+ t_materialIndex materialIndex = item->getMaterialIndex();
+ switch(item->getType())
+ {
+ case DFHack::Items::SEEDS:
+ if(!ignoreSeeds(item->flags)) ++seedCount[materialIndex];
+ break;
+ case DFHack::Items::PLANT:
+ break;
+ }
+ }
+ itemsModule.Finish();
+
+ DFHack::Kitchen::Exclusions kitchenExclusions(core);
std::map<t_materialIndex, unsigned int> watchMap;
kitchenExclusions.fillWatchMap(watchMap);
- for(std::map<t_materialIndex, unsigned int>::const_iterator i = watchMap.begin(); i != watchMap.end(); ++i)
+ for(auto i = watchMap.begin(); i != watchMap.end(); ++i)
{
if(seedCount[i->first] <= i->second)
{
- kitchenExclusions.denyCookery(i->first, seedSubindices, plantSubindices);
+ kitchenExclusions.denyPlantSeedCookery(i->first);
}
else if(i->second + buffer < seedCount[i->first])
{
- kitchenExclusions.allowCookery(i->first);
+ kitchenExclusions.allowPlantSeedCookery(i->first);
}
}
}