dfhack/tools/playground/catsplosion.cpp

181 lines
5.2 KiB
C++

2010-03-21 15:22:02 -06:00
// Catsplosion
2010-03-30 12:20:34 -06:00
// By Zhentar , Further modified by dark_rabite, peterix, belal
// This work of evil makes animals pregnant
// and due within 2 in-game hours...
2010-03-21 15:22:02 -06:00
#include <iostream>
#include <integers.h>
2010-03-30 12:20:34 -06:00
#include <cstdlib>
#include <assert.h>
#include <climits>
#include <stdlib.h> // for rand()
2010-03-30 12:20:34 -06:00
#include <algorithm> // for std::transform
#include <vector>
#include <list>
#include <iterator>
2010-03-21 15:22:02 -06:00
using namespace std;
#include <DFError.h>
2010-03-21 15:22:02 -06:00
#include <DFTypes.h>
2010-05-23 15:06:10 -06:00
#include <DFContextManager.h>
#include <DFContext.h>
2010-03-21 15:22:02 -06:00
#include <DFMemInfo.h>
#include <DFProcess.h>
2010-04-02 09:27:35 -06:00
#include <argstream.h>
2010-04-15 05:04:58 -06:00
#include <modules/Materials.h>
#include <modules/Creatures.h>
2010-03-21 15:22:02 -06:00
2010-04-15 05:04:58 -06:00
using namespace DFHack;
2010-03-30 12:20:34 -06:00
int main ( int argc, char** argv )
2010-03-21 15:22:02 -06:00
{
2010-04-15 05:04:58 -06:00
DFHack::memory_info *mem;
DFHack::Process *proc;
uint32_t creature_pregnancy_offset;
//bool femaleonly = 0;
bool showcreatures = 0;
int maxpreg = 1000; // random start value, since its not required and im not sure how to set it to infinity
list<string> s_creatures;
2010-03-30 12:20:34 -06:00
// parse input, handle this nice and neat before we get to the connecting
argstream as(argc,argv);
2010-04-15 05:04:58 -06:00
as // >>option('f',"female",femaleonly,"Impregnate females only")
2010-03-30 12:20:34 -06:00
>>option('s',"show",showcreatures,"Show creature list (read only)")
>>parameter('m',"max",maxpreg,"The maximum limit of pregnancies ", false)
>>values<string>(back_inserter(s_creatures), "any number of creatures")
>>help();
2010-04-15 05:04:58 -06:00
// make the creature list unique
s_creatures.unique();
2010-03-30 12:20:34 -06:00
if (!as.isOk())
{
2010-03-30 12:20:34 -06:00
cout << as.errorLog();
return(0);
}
else if (as.helpRequested())
{
cout<<as.usage()<<endl;
return(1);
}
else if(showcreatures==1)
{
}
else if (s_creatures.size() == 0 && showcreatures != 1)
{
2010-04-15 05:04:58 -06:00
cout << as.usage() << endl << "---------------------------------------" << endl;
cout << "Creature list empty, assuming CATs" << endl;
s_creatures.push_back("CAT");
2010-03-21 15:22:02 -06:00
}
2010-05-23 15:06:10 -06:00
DFHack::ContextManager DFMgr("Memory.xml");
DFHack::Context *DF;
try
{
2010-05-23 15:06:10 -06:00
DF = DFMgr.getSingleContext();
DF->Attach();
}
catch (exception& e)
2010-03-21 15:22:02 -06:00
{
cerr << e.what() << endl;
#ifndef LINUX_BUILD
cin.ignore();
#endif
2010-03-21 15:22:02 -06:00
return 1;
}
2010-03-21 15:22:02 -06:00
2010-05-23 15:06:10 -06:00
proc = DF->getProcess();
mem = DF->getMemoryInfo();
DFHack::Materials *Mats = DF->getMaterials();
DFHack::Creatures *Cre = DF->getCreatures();
creature_pregnancy_offset = mem->getOffset("creature_pregnancy");
2010-03-21 15:22:02 -06:00
2010-04-28 10:09:32 -06:00
if(!Mats->ReadCreatureTypesEx())
2010-03-21 15:22:02 -06:00
{
cerr << "Can't get the creature types." << endl;
#ifndef LINUX_BUILD
cin.ignore();
#endif
2010-03-30 12:20:34 -06:00
return 1;
2010-03-21 15:22:02 -06:00
}
2010-03-21 15:22:02 -06:00
uint32_t numCreatures;
2010-04-15 05:04:58 -06:00
if(!Cre->Start(numCreatures))
2010-03-21 15:22:02 -06:00
{
cerr << "Can't get creatures" << endl;
#ifndef LINUX_BUILD
cin.ignore();
#endif
2010-03-21 15:22:02 -06:00
return 1;
}
2010-03-30 12:20:34 -06:00
int totalcount=0;
int totalchanged=0;
string sextype;
// shows all the creatures and returns.
2010-04-15 05:04:58 -06:00
int maxlength = 0;
map<string, vector <t_creature> > male_counts;
map<string, vector <t_creature> > female_counts;
// classify
for(uint32_t i =0;i < numCreatures;i++)
2010-03-30 12:20:34 -06:00
{
2010-04-15 05:04:58 -06:00
DFHack::t_creature creature;
Cre->ReadCreature(i,creature);
2010-04-28 10:09:32 -06:00
DFHack::t_creaturetype & crt = Mats->raceEx[creature.race];
2010-04-15 05:04:58 -06:00
string castename = crt.castes[creature.sex].rawname;
if(castename == "FEMALE")
2010-03-30 12:20:34 -06:00
{
2010-04-28 10:09:32 -06:00
female_counts[Mats->raceEx[creature.race].rawname].push_back(creature);
male_counts[Mats->raceEx[creature.race].rawname].size();
2010-03-30 12:20:34 -06:00
}
2010-04-15 05:04:58 -06:00
else // male, other, etc.
2010-03-30 12:20:34 -06:00
{
2010-04-28 10:09:32 -06:00
male_counts[Mats->raceEx[creature.race].rawname].push_back(creature);
female_counts[Mats->raceEx[creature.race].rawname].size(); //auto initialize the females as well
2010-03-30 12:20:34 -06:00
}
}
2010-04-15 05:04:58 -06:00
// print (optional)
if (showcreatures == 1)
2010-03-21 15:22:02 -06:00
{
2010-04-15 05:04:58 -06:00
cout << "Type\t\tMale #\tFemale #" << endl;
for(map<string, vector <t_creature> >::iterator it1 = male_counts.begin();it1!=male_counts.end();it1++)
2010-03-30 12:20:34 -06:00
{
2010-04-15 05:04:58 -06:00
cout << it1->first << "\t\t" << it1->second.size() << "\t" << female_counts[it1->first].size() << endl;
2010-03-30 12:20:34 -06:00
}
2010-04-15 05:04:58 -06:00
}
// process
for (list<string>::iterator it = s_creatures.begin(); it != s_creatures.end(); ++it)
{
std::string clinput = *it;
std::transform(clinput.begin(), clinput.end(), clinput.begin(), ::toupper);
vector <t_creature> &females = female_counts[clinput];
uint32_t sz_fem = females.size();
totalcount += sz_fem;
for(uint32_t i = 0; i < sz_fem && totalchanged != maxpreg; i++)
2010-03-30 12:20:34 -06:00
{
2010-04-15 05:04:58 -06:00
t_creature & female = females[i];
uint32_t preg_timer = proc->readDWord(female.origin + creature_pregnancy_offset);
if(preg_timer != 0)
2010-03-30 12:20:34 -06:00
{
2010-04-15 05:04:58 -06:00
proc->writeDWord(female.origin + creature_pregnancy_offset, rand() % 100 + 1);
totalchanged++;
2010-03-30 12:20:34 -06:00
}
}
2010-03-21 15:22:02 -06:00
}
2010-04-15 05:04:58 -06:00
cout << totalchanged << " pregnancies accelerated. Total creatures checked: " << totalcount << "." << endl;
Cre->Finish();
2010-05-23 15:06:10 -06:00
DF->Detach();
2010-03-21 15:22:02 -06:00
#ifndef LINUX_BUILD
cout << "Done. Press any key to continue" << endl;
cin.ignore();
2010-03-21 15:22:02 -06:00
#endif
return 0;
2010-04-28 10:09:32 -06:00
}