From 0f23aba89db2d7d6d276cdc94c2e99cf43b6dcc5 Mon Sep 17 00:00:00 2001
From: Quietust
Date: Wed, 11 Jul 2012 14:31:47 -0500
Subject: [PATCH 01/92] Sync with df-structures
---
plugins/fixpositions.cpp | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/plugins/fixpositions.cpp b/plugins/fixpositions.cpp
index 086848fec..bd8fb2791 100644
--- a/plugins/fixpositions.cpp
+++ b/plugins/fixpositions.cpp
@@ -80,9 +80,9 @@ command_result df_fixdiplomats (color_ostream &out, vector ¶meters)
pos->flags.set(entity_position_flags::IS_DIPLOMAT);
pos->flags.set(entity_position_flags::IS_LEADER);
// not sure what these flags do, but the game sets them for a valid diplomat
- pos->flags.set(entity_position_flags::anon_1);
- pos->flags.set(entity_position_flags::anon_3);
- pos->flags.set(entity_position_flags::anon_4);
+ pos->flags.set(entity_position_flags::unk_12);
+ pos->flags.set(entity_position_flags::unk_1a);
+ pos->flags.set(entity_position_flags::unk_1b);
pos->name[0] = "Diplomat";
pos->name[1] = "Diplomats";
pos->precedence = 70;
@@ -183,9 +183,9 @@ command_result df_fixmerchants (color_ostream &out, vector ¶meters)
pos->flags.set(entity_position_flags::IS_DIPLOMAT);
pos->flags.set(entity_position_flags::IS_LEADER);
// not sure what these flags do, but the game sets them for a valid guild rep
- pos->flags.set(entity_position_flags::anon_1);
- pos->flags.set(entity_position_flags::anon_3);
- pos->flags.set(entity_position_flags::anon_4);
+ pos->flags.set(entity_position_flags::unk_12);
+ pos->flags.set(entity_position_flags::unk_1a);
+ pos->flags.set(entity_position_flags::unk_1b);
pos->name[0] = "Guild Representative";
pos->name[1] = "Guild Representatives";
pos->precedence = 40;
From 2695d5509006efc63a3ab6c8f6e096bad6f9aad9 Mon Sep 17 00:00:00 2001
From: Quietust
Date: Tue, 17 Jul 2012 10:27:30 -0500
Subject: [PATCH 02/92] Make indentation consistent (spaces), only display "not
enabled" error if you actually try to do something
---
plugins/autolabor.cpp | 1780 +++++++++++++++++++++--------------------
1 file changed, 896 insertions(+), 884 deletions(-)
diff --git a/plugins/autolabor.cpp b/plugins/autolabor.cpp
index 3bae1e1b3..9317c595c 100644
--- a/plugins/autolabor.cpp
+++ b/plugins/autolabor.cpp
@@ -90,265 +90,265 @@ command_result autolabor (color_ostream &out, std::vector & parame
DFHACK_PLUGIN("autolabor");
enum labor_mode {
- DISABLE,
- HAULERS,
- AUTOMATIC,
+ DISABLE,
+ HAULERS,
+ AUTOMATIC,
};
enum dwarf_state {
- // Ready for a new task
- IDLE,
+ // Ready for a new task
+ IDLE,
- // Busy with a useful task
- BUSY,
+ // Busy with a useful task
+ BUSY,
- // In the military, can't work
- MILITARY,
+ // In the military, can't work
+ MILITARY,
- // Child or noble, can't work
- CHILD,
+ // Child or noble, can't work
+ CHILD,
- // Doing something that precludes working, may be busy for a while
- OTHER
+ // Doing something that precludes working, may be busy for a while
+ OTHER
};
const int NUM_STATE = 5;
static const char *state_names[] = {
- "IDLE",
- "BUSY",
- "MILITARY",
- "CHILD",
- "OTHER",
+ "IDLE",
+ "BUSY",
+ "MILITARY",
+ "CHILD",
+ "OTHER",
};
static const dwarf_state dwarf_states[] = {
- BUSY /* CarveFortification */,
- BUSY /* DetailWall */,
- BUSY /* DetailFloor */,
- BUSY /* Dig */,
- BUSY /* CarveUpwardStaircase */,
- BUSY /* CarveDownwardStaircase */,
- BUSY /* CarveUpDownStaircase */,
- BUSY /* CarveRamp */,
- BUSY /* DigChannel */,
- BUSY /* FellTree */,
- BUSY /* GatherPlants */,
- BUSY /* RemoveConstruction */,
- BUSY /* CollectWebs */,
- BUSY /* BringItemToDepot */,
- BUSY /* BringItemToShop */,
- OTHER /* Eat */,
- OTHER /* GetProvisions */,
- OTHER /* Drink */,
- OTHER /* Drink2 */,
- OTHER /* FillWaterskin */,
- OTHER /* FillWaterskin2 */,
- OTHER /* Sleep */,
- BUSY /* CollectSand */,
- BUSY /* Fish */,
- BUSY /* Hunt */,
- OTHER /* HuntVermin */,
- BUSY /* Kidnap */,
- BUSY /* BeatCriminal */,
- BUSY /* StartingFistFight */,
- BUSY /* CollectTaxes */,
- BUSY /* GuardTaxCollector */,
- BUSY /* CatchLiveLandAnimal */,
- BUSY /* CatchLiveFish */,
- BUSY /* ReturnKill */,
- BUSY /* CheckChest */,
- BUSY /* StoreOwnedItem */,
- BUSY /* PlaceItemInTomb */,
- BUSY /* StoreItemInStockpile */,
- BUSY /* StoreItemInBag */,
- BUSY /* StoreItemInHospital */,
- BUSY /* StoreItemInChest */,
- BUSY /* StoreItemInCabinet */,
- BUSY /* StoreWeapon */,
- BUSY /* StoreArmor */,
- BUSY /* StoreItemInBarrel */,
- BUSY /* StoreItemInBin */,
- BUSY /* SeekArtifact */,
- BUSY /* SeekInfant */,
- OTHER /* AttendParty */,
- OTHER /* GoShopping */,
- OTHER /* GoShopping2 */,
- BUSY /* Clean */,
- OTHER /* Rest */,
- BUSY /* PickupEquipment */,
- BUSY /* DumpItem */,
- OTHER /* StrangeMoodCrafter */,
- OTHER /* StrangeMoodJeweller */,
- OTHER /* StrangeMoodForge */,
- OTHER /* StrangeMoodMagmaForge */,
- OTHER /* StrangeMoodBrooding */,
- OTHER /* StrangeMoodFell */,
- OTHER /* StrangeMoodCarpenter */,
- OTHER /* StrangeMoodMason */,
- OTHER /* StrangeMoodBowyer */,
- OTHER /* StrangeMoodTanner */,
- OTHER /* StrangeMoodWeaver */,
- OTHER /* StrangeMoodGlassmaker */,
- OTHER /* StrangeMoodMechanics */,
- BUSY /* ConstructBuilding */,
- BUSY /* ConstructDoor */,
- BUSY /* ConstructFloodgate */,
- BUSY /* ConstructBed */,
- BUSY /* ConstructThrone */,
- BUSY /* ConstructCoffin */,
- BUSY /* ConstructTable */,
- BUSY /* ConstructChest */,
- BUSY /* ConstructBin */,
- BUSY /* ConstructArmorStand */,
- BUSY /* ConstructWeaponRack */,
- BUSY /* ConstructCabinet */,
- BUSY /* ConstructStatue */,
- BUSY /* ConstructBlocks */,
- BUSY /* MakeRawGlass */,
- BUSY /* MakeCrafts */,
- BUSY /* MintCoins */,
- BUSY /* CutGems */,
- BUSY /* CutGlass */,
- BUSY /* EncrustWithGems */,
- BUSY /* EncrustWithGlass */,
- BUSY /* DestroyBuilding */,
- BUSY /* SmeltOre */,
- BUSY /* MeltMetalObject */,
- BUSY /* ExtractMetalStrands */,
- BUSY /* PlantSeeds */,
- BUSY /* HarvestPlants */,
- BUSY /* TrainHuntingAnimal */,
- BUSY /* TrainWarAnimal */,
- BUSY /* MakeWeapon */,
- BUSY /* ForgeAnvil */,
- BUSY /* ConstructCatapultParts */,
- BUSY /* ConstructBallistaParts */,
- BUSY /* MakeArmor */,
- BUSY /* MakeHelm */,
- BUSY /* MakePants */,
- BUSY /* StudWith */,
- BUSY /* ButcherAnimal */,
- BUSY /* PrepareRawFish */,
- BUSY /* MillPlants */,
- BUSY /* BaitTrap */,
- BUSY /* MilkCreature */,
- BUSY /* MakeCheese */,
- BUSY /* ProcessPlants */,
- BUSY /* ProcessPlantsBag */,
- BUSY /* ProcessPlantsVial */,
- BUSY /* ProcessPlantsBarrel */,
- BUSY /* PrepareMeal */,
- BUSY /* WeaveCloth */,
- BUSY /* MakeGloves */,
- BUSY /* MakeShoes */,
- BUSY /* MakeShield */,
- BUSY /* MakeCage */,
- BUSY /* MakeChain */,
- BUSY /* MakeFlask */,
- BUSY /* MakeGoblet */,
- BUSY /* MakeInstrument */,
- BUSY /* MakeToy */,
- BUSY /* MakeAnimalTrap */,
- BUSY /* MakeBarrel */,
- BUSY /* MakeBucket */,
- BUSY /* MakeWindow */,
- BUSY /* MakeTotem */,
- BUSY /* MakeAmmo */,
- BUSY /* DecorateWith */,
- BUSY /* MakeBackpack */,
- BUSY /* MakeQuiver */,
- BUSY /* MakeBallistaArrowHead */,
- BUSY /* AssembleSiegeAmmo */,
- BUSY /* LoadCatapult */,
- BUSY /* LoadBallista */,
- BUSY /* FireCatapult */,
- BUSY /* FireBallista */,
- BUSY /* ConstructMechanisms */,
- BUSY /* MakeTrapComponent */,
- BUSY /* LoadCageTrap */,
- BUSY /* LoadStoneTrap */,
- BUSY /* LoadWeaponTrap */,
- BUSY /* CleanTrap */,
- BUSY /* CastSpell */,
- BUSY /* LinkBuildingToTrigger */,
- BUSY /* PullLever */,
- BUSY /* BrewDrink */,
- BUSY /* ExtractFromPlants */,
- BUSY /* ExtractFromRawFish */,
- BUSY /* ExtractFromLandAnimal */,
- BUSY /* TameVermin */,
- BUSY /* TameAnimal */,
- BUSY /* ChainAnimal */,
- BUSY /* UnchainAnimal */,
- BUSY /* UnchainPet */,
- BUSY /* ReleaseLargeCreature */,
- BUSY /* ReleasePet */,
- BUSY /* ReleaseSmallCreature */,
- BUSY /* HandleSmallCreature */,
- BUSY /* HandleLargeCreature */,
- BUSY /* CageLargeCreature */,
- BUSY /* CageSmallCreature */,
- BUSY /* RecoverWounded */,
- BUSY /* DiagnosePatient */,
- BUSY /* ImmobilizeBreak */,
- BUSY /* DressWound */,
- BUSY /* CleanPatient */,
- BUSY /* Surgery */,
- BUSY /* Suture */,
- BUSY /* SetBone */,
- BUSY /* PlaceInTraction */,
- BUSY /* DrainAquarium */,
- BUSY /* FillAquarium */,
- BUSY /* FillPond */,
- BUSY /* GiveWater */,
- BUSY /* GiveFood */,
- BUSY /* GiveWater2 */,
- BUSY /* GiveFood2 */,
- BUSY /* RecoverPet */,
- BUSY /* PitLargeAnimal */,
- BUSY /* PitSmallAnimal */,
- BUSY /* SlaughterAnimal */,
- BUSY /* MakeCharcoal */,
- BUSY /* MakeAsh */,
- BUSY /* MakeLye */,
- BUSY /* MakePotashFromLye */,
- BUSY /* FertilizeField */,
- BUSY /* MakePotashFromAsh */,
- BUSY /* DyeThread */,
- BUSY /* DyeCloth */,
- BUSY /* SewImage */,
- BUSY /* MakePipeSection */,
- BUSY /* OperatePump */,
- OTHER /* ManageWorkOrders */,
- OTHER /* UpdateStockpileRecords */,
- OTHER /* TradeAtDepot */,
- BUSY /* ConstructHatchCover */,
- BUSY /* ConstructGrate */,
- BUSY /* RemoveStairs */,
- BUSY /* ConstructQuern */,
- BUSY /* ConstructMillstone */,
- BUSY /* ConstructSplint */,
- BUSY /* ConstructCrutch */,
- BUSY /* ConstructTractionBench */,
- BUSY /* CleanSelf */,
- BUSY /* BringCrutch */,
- BUSY /* ApplyCast */,
- BUSY /* CustomReaction */,
- BUSY /* ConstructSlab */,
- BUSY /* EngraveSlab */,
- BUSY /* ShearCreature */,
- BUSY /* SpinThread */,
- BUSY /* PenLargeAnimal */,
- BUSY /* PenSmallAnimal */,
- BUSY /* MakeTool */,
- BUSY /* CollectClay */,
- BUSY /* InstallColonyInHive */,
- BUSY /* CollectHiveProducts */,
- OTHER /* CauseTrouble */,
- OTHER /* DrinkBlood */,
- OTHER /* ReportCrime */,
- OTHER /* ExecuteCriminal */,
+ BUSY /* CarveFortification */,
+ BUSY /* DetailWall */,
+ BUSY /* DetailFloor */,
+ BUSY /* Dig */,
+ BUSY /* CarveUpwardStaircase */,
+ BUSY /* CarveDownwardStaircase */,
+ BUSY /* CarveUpDownStaircase */,
+ BUSY /* CarveRamp */,
+ BUSY /* DigChannel */,
+ BUSY /* FellTree */,
+ BUSY /* GatherPlants */,
+ BUSY /* RemoveConstruction */,
+ BUSY /* CollectWebs */,
+ BUSY /* BringItemToDepot */,
+ BUSY /* BringItemToShop */,
+ OTHER /* Eat */,
+ OTHER /* GetProvisions */,
+ OTHER /* Drink */,
+ OTHER /* Drink2 */,
+ OTHER /* FillWaterskin */,
+ OTHER /* FillWaterskin2 */,
+ OTHER /* Sleep */,
+ BUSY /* CollectSand */,
+ BUSY /* Fish */,
+ BUSY /* Hunt */,
+ OTHER /* HuntVermin */,
+ BUSY /* Kidnap */,
+ BUSY /* BeatCriminal */,
+ BUSY /* StartingFistFight */,
+ BUSY /* CollectTaxes */,
+ BUSY /* GuardTaxCollector */,
+ BUSY /* CatchLiveLandAnimal */,
+ BUSY /* CatchLiveFish */,
+ BUSY /* ReturnKill */,
+ BUSY /* CheckChest */,
+ BUSY /* StoreOwnedItem */,
+ BUSY /* PlaceItemInTomb */,
+ BUSY /* StoreItemInStockpile */,
+ BUSY /* StoreItemInBag */,
+ BUSY /* StoreItemInHospital */,
+ BUSY /* StoreItemInChest */,
+ BUSY /* StoreItemInCabinet */,
+ BUSY /* StoreWeapon */,
+ BUSY /* StoreArmor */,
+ BUSY /* StoreItemInBarrel */,
+ BUSY /* StoreItemInBin */,
+ BUSY /* SeekArtifact */,
+ BUSY /* SeekInfant */,
+ OTHER /* AttendParty */,
+ OTHER /* GoShopping */,
+ OTHER /* GoShopping2 */,
+ BUSY /* Clean */,
+ OTHER /* Rest */,
+ BUSY /* PickupEquipment */,
+ BUSY /* DumpItem */,
+ OTHER /* StrangeMoodCrafter */,
+ OTHER /* StrangeMoodJeweller */,
+ OTHER /* StrangeMoodForge */,
+ OTHER /* StrangeMoodMagmaForge */,
+ OTHER /* StrangeMoodBrooding */,
+ OTHER /* StrangeMoodFell */,
+ OTHER /* StrangeMoodCarpenter */,
+ OTHER /* StrangeMoodMason */,
+ OTHER /* StrangeMoodBowyer */,
+ OTHER /* StrangeMoodTanner */,
+ OTHER /* StrangeMoodWeaver */,
+ OTHER /* StrangeMoodGlassmaker */,
+ OTHER /* StrangeMoodMechanics */,
+ BUSY /* ConstructBuilding */,
+ BUSY /* ConstructDoor */,
+ BUSY /* ConstructFloodgate */,
+ BUSY /* ConstructBed */,
+ BUSY /* ConstructThrone */,
+ BUSY /* ConstructCoffin */,
+ BUSY /* ConstructTable */,
+ BUSY /* ConstructChest */,
+ BUSY /* ConstructBin */,
+ BUSY /* ConstructArmorStand */,
+ BUSY /* ConstructWeaponRack */,
+ BUSY /* ConstructCabinet */,
+ BUSY /* ConstructStatue */,
+ BUSY /* ConstructBlocks */,
+ BUSY /* MakeRawGlass */,
+ BUSY /* MakeCrafts */,
+ BUSY /* MintCoins */,
+ BUSY /* CutGems */,
+ BUSY /* CutGlass */,
+ BUSY /* EncrustWithGems */,
+ BUSY /* EncrustWithGlass */,
+ BUSY /* DestroyBuilding */,
+ BUSY /* SmeltOre */,
+ BUSY /* MeltMetalObject */,
+ BUSY /* ExtractMetalStrands */,
+ BUSY /* PlantSeeds */,
+ BUSY /* HarvestPlants */,
+ BUSY /* TrainHuntingAnimal */,
+ BUSY /* TrainWarAnimal */,
+ BUSY /* MakeWeapon */,
+ BUSY /* ForgeAnvil */,
+ BUSY /* ConstructCatapultParts */,
+ BUSY /* ConstructBallistaParts */,
+ BUSY /* MakeArmor */,
+ BUSY /* MakeHelm */,
+ BUSY /* MakePants */,
+ BUSY /* StudWith */,
+ BUSY /* ButcherAnimal */,
+ BUSY /* PrepareRawFish */,
+ BUSY /* MillPlants */,
+ BUSY /* BaitTrap */,
+ BUSY /* MilkCreature */,
+ BUSY /* MakeCheese */,
+ BUSY /* ProcessPlants */,
+ BUSY /* ProcessPlantsBag */,
+ BUSY /* ProcessPlantsVial */,
+ BUSY /* ProcessPlantsBarrel */,
+ BUSY /* PrepareMeal */,
+ BUSY /* WeaveCloth */,
+ BUSY /* MakeGloves */,
+ BUSY /* MakeShoes */,
+ BUSY /* MakeShield */,
+ BUSY /* MakeCage */,
+ BUSY /* MakeChain */,
+ BUSY /* MakeFlask */,
+ BUSY /* MakeGoblet */,
+ BUSY /* MakeInstrument */,
+ BUSY /* MakeToy */,
+ BUSY /* MakeAnimalTrap */,
+ BUSY /* MakeBarrel */,
+ BUSY /* MakeBucket */,
+ BUSY /* MakeWindow */,
+ BUSY /* MakeTotem */,
+ BUSY /* MakeAmmo */,
+ BUSY /* DecorateWith */,
+ BUSY /* MakeBackpack */,
+ BUSY /* MakeQuiver */,
+ BUSY /* MakeBallistaArrowHead */,
+ BUSY /* AssembleSiegeAmmo */,
+ BUSY /* LoadCatapult */,
+ BUSY /* LoadBallista */,
+ BUSY /* FireCatapult */,
+ BUSY /* FireBallista */,
+ BUSY /* ConstructMechanisms */,
+ BUSY /* MakeTrapComponent */,
+ BUSY /* LoadCageTrap */,
+ BUSY /* LoadStoneTrap */,
+ BUSY /* LoadWeaponTrap */,
+ BUSY /* CleanTrap */,
+ BUSY /* CastSpell */,
+ BUSY /* LinkBuildingToTrigger */,
+ BUSY /* PullLever */,
+ BUSY /* BrewDrink */,
+ BUSY /* ExtractFromPlants */,
+ BUSY /* ExtractFromRawFish */,
+ BUSY /* ExtractFromLandAnimal */,
+ BUSY /* TameVermin */,
+ BUSY /* TameAnimal */,
+ BUSY /* ChainAnimal */,
+ BUSY /* UnchainAnimal */,
+ BUSY /* UnchainPet */,
+ BUSY /* ReleaseLargeCreature */,
+ BUSY /* ReleasePet */,
+ BUSY /* ReleaseSmallCreature */,
+ BUSY /* HandleSmallCreature */,
+ BUSY /* HandleLargeCreature */,
+ BUSY /* CageLargeCreature */,
+ BUSY /* CageSmallCreature */,
+ BUSY /* RecoverWounded */,
+ BUSY /* DiagnosePatient */,
+ BUSY /* ImmobilizeBreak */,
+ BUSY /* DressWound */,
+ BUSY /* CleanPatient */,
+ BUSY /* Surgery */,
+ BUSY /* Suture */,
+ BUSY /* SetBone */,
+ BUSY /* PlaceInTraction */,
+ BUSY /* DrainAquarium */,
+ BUSY /* FillAquarium */,
+ BUSY /* FillPond */,
+ BUSY /* GiveWater */,
+ BUSY /* GiveFood */,
+ BUSY /* GiveWater2 */,
+ BUSY /* GiveFood2 */,
+ BUSY /* RecoverPet */,
+ BUSY /* PitLargeAnimal */,
+ BUSY /* PitSmallAnimal */,
+ BUSY /* SlaughterAnimal */,
+ BUSY /* MakeCharcoal */,
+ BUSY /* MakeAsh */,
+ BUSY /* MakeLye */,
+ BUSY /* MakePotashFromLye */,
+ BUSY /* FertilizeField */,
+ BUSY /* MakePotashFromAsh */,
+ BUSY /* DyeThread */,
+ BUSY /* DyeCloth */,
+ BUSY /* SewImage */,
+ BUSY /* MakePipeSection */,
+ BUSY /* OperatePump */,
+ OTHER /* ManageWorkOrders */,
+ OTHER /* UpdateStockpileRecords */,
+ OTHER /* TradeAtDepot */,
+ BUSY /* ConstructHatchCover */,
+ BUSY /* ConstructGrate */,
+ BUSY /* RemoveStairs */,
+ BUSY /* ConstructQuern */,
+ BUSY /* ConstructMillstone */,
+ BUSY /* ConstructSplint */,
+ BUSY /* ConstructCrutch */,
+ BUSY /* ConstructTractionBench */,
+ BUSY /* CleanSelf */,
+ BUSY /* BringCrutch */,
+ BUSY /* ApplyCast */,
+ BUSY /* CustomReaction */,
+ BUSY /* ConstructSlab */,
+ BUSY /* EngraveSlab */,
+ BUSY /* ShearCreature */,
+ BUSY /* SpinThread */,
+ BUSY /* PenLargeAnimal */,
+ BUSY /* PenSmallAnimal */,
+ BUSY /* MakeTool */,
+ BUSY /* CollectClay */,
+ BUSY /* InstallColonyInHive */,
+ BUSY /* CollectHiveProducts */,
+ OTHER /* CauseTrouble */,
+ OTHER /* DrinkBlood */,
+ OTHER /* ReportCrime */,
+ OTHER /* ExecuteCriminal */,
BUSY /* TrainAnimal */,
BUSY /* CarveTrack */,
BUSY /* PushTrackVehicle */,
@@ -360,106 +360,106 @@ struct labor_info
{
PersistentDataItem config;
- bool is_exclusive;
- int active_dwarfs;
+ bool is_exclusive;
+ int active_dwarfs;
- labor_mode mode() { return (labor_mode) config.ival(0); }
- void set_mode(labor_mode mode) { config.ival(0) = mode; }
+ labor_mode mode() { return (labor_mode) config.ival(0); }
+ void set_mode(labor_mode mode) { config.ival(0) = mode; }
- int minimum_dwarfs() { return config.ival(1); }
- void set_minimum_dwarfs(int minimum_dwarfs) { config.ival(1) = minimum_dwarfs; }
+ int minimum_dwarfs() { return config.ival(1); }
+ void set_minimum_dwarfs(int minimum_dwarfs) { config.ival(1) = minimum_dwarfs; }
- int maximum_dwarfs() { return config.ival(2); }
- void set_maximum_dwarfs(int maximum_dwarfs) { config.ival(2) = maximum_dwarfs; }
+ int maximum_dwarfs() { return config.ival(2); }
+ void set_maximum_dwarfs(int maximum_dwarfs) { config.ival(2) = maximum_dwarfs; }
};
struct labor_default
{
- labor_mode mode;
- bool is_exclusive;
- int minimum_dwarfs;
- int maximum_dwarfs;
- int active_dwarfs;
+ labor_mode mode;
+ bool is_exclusive;
+ int minimum_dwarfs;
+ int maximum_dwarfs;
+ int active_dwarfs;
};
static std::vector labor_infos;
static const struct labor_default default_labor_infos[] = {
- /* MINE */ {AUTOMATIC, true, 2, 200, 0},
- /* HAUL_STONE */ {HAULERS, false, 1, 200, 0},
- /* HAUL_WOOD */ {HAULERS, false, 1, 200, 0},
- /* HAUL_BODY */ {HAULERS, false, 1, 200, 0},
- /* HAUL_FOOD */ {HAULERS, false, 1, 200, 0},
- /* HAUL_REFUSE */ {HAULERS, false, 1, 200, 0},
- /* HAUL_ITEM */ {HAULERS, false, 1, 200, 0},
- /* HAUL_FURNITURE */ {HAULERS, false, 1, 200, 0},
- /* HAUL_ANIMAL */ {HAULERS, false, 1, 200, 0},
- /* CLEAN */ {HAULERS, false, 1, 200, 0},
- /* CUTWOOD */ {AUTOMATIC, true, 1, 200, 0},
- /* CARPENTER */ {AUTOMATIC, false, 1, 200, 0},
- /* DETAIL */ {AUTOMATIC, false, 1, 200, 0},
- /* MASON */ {AUTOMATIC, false, 1, 200, 0},
- /* ARCHITECT */ {AUTOMATIC, false, 1, 200, 0},
- /* ANIMALTRAIN */ {AUTOMATIC, false, 1, 200, 0},
- /* ANIMALCARE */ {AUTOMATIC, false, 1, 200, 0},
- /* DIAGNOSE */ {AUTOMATIC, false, 1, 200, 0},
- /* SURGERY */ {AUTOMATIC, false, 1, 200, 0},
- /* BONE_SETTING */ {AUTOMATIC, false, 1, 200, 0},
- /* SUTURING */ {AUTOMATIC, false, 1, 200, 0},
- /* DRESSING_WOUNDS */ {AUTOMATIC, false, 1, 200, 0},
- /* FEED_WATER_CIVILIANS */ {AUTOMATIC, false, 200, 200, 0},
- /* RECOVER_WOUNDED */ {HAULERS, false, 1, 200, 0},
- /* BUTCHER */ {AUTOMATIC, false, 1, 200, 0},
- /* TRAPPER */ {AUTOMATIC, false, 1, 200, 0},
- /* DISSECT_VERMIN */ {AUTOMATIC, false, 1, 200, 0},
- /* LEATHER */ {AUTOMATIC, false, 1, 200, 0},
- /* TANNER */ {AUTOMATIC, false, 1, 200, 0},
- /* BREWER */ {AUTOMATIC, false, 1, 200, 0},
- /* ALCHEMIST */ {AUTOMATIC, false, 1, 200, 0},
- /* SOAP_MAKER */ {AUTOMATIC, false, 1, 200, 0},
- /* WEAVER */ {AUTOMATIC, false, 1, 200, 0},
- /* CLOTHESMAKER */ {AUTOMATIC, false, 1, 200, 0},
- /* MILLER */ {AUTOMATIC, false, 1, 200, 0},
- /* PROCESS_PLANT */ {AUTOMATIC, false, 1, 200, 0},
- /* MAKE_CHEESE */ {AUTOMATIC, false, 1, 200, 0},
- /* MILK */ {AUTOMATIC, false, 1, 200, 0},
- /* COOK */ {AUTOMATIC, false, 1, 200, 0},
- /* PLANT */ {AUTOMATIC, false, 1, 200, 0},
- /* HERBALIST */ {AUTOMATIC, false, 1, 200, 0},
- /* FISH */ {AUTOMATIC, false, 1, 1, 0},
- /* CLEAN_FISH */ {AUTOMATIC, false, 1, 200, 0},
- /* DISSECT_FISH */ {AUTOMATIC, false, 1, 200, 0},
- /* HUNT */ {AUTOMATIC, true, 1, 1, 0},
- /* SMELT */ {AUTOMATIC, false, 1, 200, 0},
- /* FORGE_WEAPON */ {AUTOMATIC, false, 1, 200, 0},
- /* FORGE_ARMOR */ {AUTOMATIC, false, 1, 200, 0},
- /* FORGE_FURNITURE */ {AUTOMATIC, false, 1, 200, 0},
- /* METAL_CRAFT */ {AUTOMATIC, false, 1, 200, 0},
- /* CUT_GEM */ {AUTOMATIC, false, 1, 200, 0},
- /* ENCRUST_GEM */ {AUTOMATIC, false, 1, 200, 0},
- /* WOOD_CRAFT */ {AUTOMATIC, false, 1, 200, 0},
- /* STONE_CRAFT */ {AUTOMATIC, false, 1, 200, 0},
- /* BONE_CARVE */ {AUTOMATIC, false, 1, 200, 0},
- /* GLASSMAKER */ {AUTOMATIC, false, 1, 200, 0},
- /* EXTRACT_STRAND */ {AUTOMATIC, false, 1, 200, 0},
- /* SIEGECRAFT */ {AUTOMATIC, false, 1, 200, 0},
- /* SIEGEOPERATE */ {AUTOMATIC, false, 1, 200, 0},
- /* BOWYER */ {AUTOMATIC, false, 1, 200, 0},
- /* MECHANIC */ {AUTOMATIC, false, 1, 200, 0},
- /* POTASH_MAKING */ {AUTOMATIC, false, 1, 200, 0},
- /* LYE_MAKING */ {AUTOMATIC, false, 1, 200, 0},
- /* DYER */ {AUTOMATIC, false, 1, 200, 0},
- /* BURN_WOOD */ {AUTOMATIC, false, 1, 200, 0},
- /* OPERATE_PUMP */ {AUTOMATIC, false, 1, 200, 0},
- /* SHEARER */ {AUTOMATIC, false, 1, 200, 0},
- /* SPINNER */ {AUTOMATIC, false, 1, 200, 0},
- /* POTTERY */ {AUTOMATIC, false, 1, 200, 0},
- /* GLAZING */ {AUTOMATIC, false, 1, 200, 0},
- /* PRESSING */ {AUTOMATIC, false, 1, 200, 0},
- /* BEEKEEPING */ {AUTOMATIC, false, 1, 1, 0}, // reduce risk of stuck beekeepers (see http://www.bay12games.com/dwarves/mantisbt/view.php?id=3981)
- /* WAX_WORKING */ {AUTOMATIC, false, 1, 200, 0},
- /* PUSH_HAUL_VEHICLES */ {HAULERS, false, 1, 200, 0}
+ /* MINE */ {AUTOMATIC, true, 2, 200, 0},
+ /* HAUL_STONE */ {HAULERS, false, 1, 200, 0},
+ /* HAUL_WOOD */ {HAULERS, false, 1, 200, 0},
+ /* HAUL_BODY */ {HAULERS, false, 1, 200, 0},
+ /* HAUL_FOOD */ {HAULERS, false, 1, 200, 0},
+ /* HAUL_REFUSE */ {HAULERS, false, 1, 200, 0},
+ /* HAUL_ITEM */ {HAULERS, false, 1, 200, 0},
+ /* HAUL_FURNITURE */ {HAULERS, false, 1, 200, 0},
+ /* HAUL_ANIMAL */ {HAULERS, false, 1, 200, 0},
+ /* CLEAN */ {HAULERS, false, 1, 200, 0},
+ /* CUTWOOD */ {AUTOMATIC, true, 1, 200, 0},
+ /* CARPENTER */ {AUTOMATIC, false, 1, 200, 0},
+ /* DETAIL */ {AUTOMATIC, false, 1, 200, 0},
+ /* MASON */ {AUTOMATIC, false, 1, 200, 0},
+ /* ARCHITECT */ {AUTOMATIC, false, 1, 200, 0},
+ /* ANIMALTRAIN */ {AUTOMATIC, false, 1, 200, 0},
+ /* ANIMALCARE */ {AUTOMATIC, false, 1, 200, 0},
+ /* DIAGNOSE */ {AUTOMATIC, false, 1, 200, 0},
+ /* SURGERY */ {AUTOMATIC, false, 1, 200, 0},
+ /* BONE_SETTING */ {AUTOMATIC, false, 1, 200, 0},
+ /* SUTURING */ {AUTOMATIC, false, 1, 200, 0},
+ /* DRESSING_WOUNDS */ {AUTOMATIC, false, 1, 200, 0},
+ /* FEED_WATER_CIVILIANS */ {AUTOMATIC, false, 200, 200, 0},
+ /* RECOVER_WOUNDED */ {HAULERS, false, 1, 200, 0},
+ /* BUTCHER */ {AUTOMATIC, false, 1, 200, 0},
+ /* TRAPPER */ {AUTOMATIC, false, 1, 200, 0},
+ /* DISSECT_VERMIN */ {AUTOMATIC, false, 1, 200, 0},
+ /* LEATHER */ {AUTOMATIC, false, 1, 200, 0},
+ /* TANNER */ {AUTOMATIC, false, 1, 200, 0},
+ /* BREWER */ {AUTOMATIC, false, 1, 200, 0},
+ /* ALCHEMIST */ {AUTOMATIC, false, 1, 200, 0},
+ /* SOAP_MAKER */ {AUTOMATIC, false, 1, 200, 0},
+ /* WEAVER */ {AUTOMATIC, false, 1, 200, 0},
+ /* CLOTHESMAKER */ {AUTOMATIC, false, 1, 200, 0},
+ /* MILLER */ {AUTOMATIC, false, 1, 200, 0},
+ /* PROCESS_PLANT */ {AUTOMATIC, false, 1, 200, 0},
+ /* MAKE_CHEESE */ {AUTOMATIC, false, 1, 200, 0},
+ /* MILK */ {AUTOMATIC, false, 1, 200, 0},
+ /* COOK */ {AUTOMATIC, false, 1, 200, 0},
+ /* PLANT */ {AUTOMATIC, false, 1, 200, 0},
+ /* HERBALIST */ {AUTOMATIC, false, 1, 200, 0},
+ /* FISH */ {AUTOMATIC, false, 1, 1, 0},
+ /* CLEAN_FISH */ {AUTOMATIC, false, 1, 200, 0},
+ /* DISSECT_FISH */ {AUTOMATIC, false, 1, 200, 0},
+ /* HUNT */ {AUTOMATIC, true, 1, 1, 0},
+ /* SMELT */ {AUTOMATIC, false, 1, 200, 0},
+ /* FORGE_WEAPON */ {AUTOMATIC, false, 1, 200, 0},
+ /* FORGE_ARMOR */ {AUTOMATIC, false, 1, 200, 0},
+ /* FORGE_FURNITURE */ {AUTOMATIC, false, 1, 200, 0},
+ /* METAL_CRAFT */ {AUTOMATIC, false, 1, 200, 0},
+ /* CUT_GEM */ {AUTOMATIC, false, 1, 200, 0},
+ /* ENCRUST_GEM */ {AUTOMATIC, false, 1, 200, 0},
+ /* WOOD_CRAFT */ {AUTOMATIC, false, 1, 200, 0},
+ /* STONE_CRAFT */ {AUTOMATIC, false, 1, 200, 0},
+ /* BONE_CARVE */ {AUTOMATIC, false, 1, 200, 0},
+ /* GLASSMAKER */ {AUTOMATIC, false, 1, 200, 0},
+ /* EXTRACT_STRAND */ {AUTOMATIC, false, 1, 200, 0},
+ /* SIEGECRAFT */ {AUTOMATIC, false, 1, 200, 0},
+ /* SIEGEOPERATE */ {AUTOMATIC, false, 1, 200, 0},
+ /* BOWYER */ {AUTOMATIC, false, 1, 200, 0},
+ /* MECHANIC */ {AUTOMATIC, false, 1, 200, 0},
+ /* POTASH_MAKING */ {AUTOMATIC, false, 1, 200, 0},
+ /* LYE_MAKING */ {AUTOMATIC, false, 1, 200, 0},
+ /* DYER */ {AUTOMATIC, false, 1, 200, 0},
+ /* BURN_WOOD */ {AUTOMATIC, false, 1, 200, 0},
+ /* OPERATE_PUMP */ {AUTOMATIC, false, 1, 200, 0},
+ /* SHEARER */ {AUTOMATIC, false, 1, 200, 0},
+ /* SPINNER */ {AUTOMATIC, false, 1, 200, 0},
+ /* POTTERY */ {AUTOMATIC, false, 1, 200, 0},
+ /* GLAZING */ {AUTOMATIC, false, 1, 200, 0},
+ /* PRESSING */ {AUTOMATIC, false, 1, 200, 0},
+ /* BEEKEEPING */ {AUTOMATIC, false, 1, 1, 0}, // reduce risk of stuck beekeepers (see http://www.bay12games.com/dwarves/mantisbt/view.php?id=3981)
+ /* WAX_WORKING */ {AUTOMATIC, false, 1, 200, 0},
+ /* PUSH_HAUL_VEHICLES */ {HAULERS, false, 1, 200, 0}
};
static const int responsibility_penalties[] = {
@@ -492,12 +492,12 @@ static const int responsibility_penalties[] = {
struct dwarf_info_t
{
- int highest_skill;
- int total_skill;
- int mastery_penalty;
- int assigned_jobs;
- dwarf_state state;
- bool has_exclusive_labor;
+ int highest_skill;
+ int total_skill;
+ int mastery_penalty;
+ int assigned_jobs;
+ dwarf_state state;
+ bool has_exclusive_labor;
int noble_penalty; // penalty for assignment due to noble status
bool medical; // this dwarf has medical responsibility
bool trader; // this dwarf has trade responsibility
@@ -521,14 +521,14 @@ static void setOptionEnabled(ConfigFlags flag, bool on)
static void cleanup_state()
{
- labor_infos.clear();
+ labor_infos.clear();
}
static void reset_labor(df::enums::unit_labor::unit_labor labor)
{
- labor_infos[labor].set_minimum_dwarfs(default_labor_infos[labor].minimum_dwarfs);
- labor_infos[labor].set_maximum_dwarfs(default_labor_infos[labor].maximum_dwarfs);
- labor_infos[labor].set_mode(default_labor_infos[labor].mode);
+ labor_infos[labor].set_minimum_dwarfs(default_labor_infos[labor].minimum_dwarfs);
+ labor_infos[labor].set_maximum_dwarfs(default_labor_infos[labor].maximum_dwarfs);
+ labor_infos[labor].set_mode(default_labor_infos[labor].mode);
}
static void init_state()
@@ -539,42 +539,42 @@ static void init_state()
if (config.isValid() && config.ival(0) == -1)
config.ival(0) = 0;
- enable_autolabor = isOptionEnabled(CF_ENABLED);
+ enable_autolabor = isOptionEnabled(CF_ENABLED);
- if (!enable_autolabor)
- return;
+ if (!enable_autolabor)
+ return;
- // Load labors from save
- labor_infos.resize(ARRAY_COUNT(default_labor_infos));
+ // Load labors from save
+ labor_infos.resize(ARRAY_COUNT(default_labor_infos));
- std::vector items;
+ std::vector items;
pworld->GetPersistentData(&items, "autolabor/labors/", true);
- for (auto p = items.begin(); p != items.end(); p++)
- {
- string key = p->key();
- df::enums::unit_labor::unit_labor labor = (df::enums::unit_labor::unit_labor) atoi(key.substr(strlen("autolabor/labors/")).c_str());
- if (labor >= 0 && labor <= labor_infos.size())
- {
- labor_infos[labor].config = *p;
- labor_infos[labor].is_exclusive = default_labor_infos[labor].is_exclusive;
- labor_infos[labor].active_dwarfs = 0;
- }
- }
-
- // Add default labors for those not in save
+ for (auto p = items.begin(); p != items.end(); p++)
+ {
+ string key = p->key();
+ df::enums::unit_labor::unit_labor labor = (df::enums::unit_labor::unit_labor) atoi(key.substr(strlen("autolabor/labors/")).c_str());
+ if (labor >= 0 && labor <= labor_infos.size())
+ {
+ labor_infos[labor].config = *p;
+ labor_infos[labor].is_exclusive = default_labor_infos[labor].is_exclusive;
+ labor_infos[labor].active_dwarfs = 0;
+ }
+ }
+
+ // Add default labors for those not in save
for (int i = 0; i < ARRAY_COUNT(default_labor_infos); i++) {
- if (labor_infos[i].config.isValid())
- continue;
+ if (labor_infos[i].config.isValid())
+ continue;
- std::stringstream name;
- name << "autolabor/labors/" << i;
+ std::stringstream name;
+ name << "autolabor/labors/" << i;
- labor_infos[i].config = pworld->AddPersistentData(name.str());
+ labor_infos[i].config = pworld->AddPersistentData(name.str());
- labor_infos[i].is_exclusive = default_labor_infos[i].is_exclusive;
- labor_infos[i].active_dwarfs = 0;
- reset_labor((df::enums::unit_labor::unit_labor) i);
+ labor_infos[i].is_exclusive = default_labor_infos[i].is_exclusive;
+ labor_infos[i].active_dwarfs = 0;
+ reset_labor((df::enums::unit_labor::unit_labor) i);
}
}
@@ -592,8 +592,8 @@ static void enable_plugin(color_ostream &out)
enable_autolabor = true;
out << "Enabling the plugin." << endl;
- cleanup_state();
- init_state();
+ cleanup_state();
+ init_state();
}
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands)
@@ -608,49 +608,49 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector []\n"
- " Set number of dwarves assigned to a labor.\n"
- " autolabor haulers\n"
- " Set a labor to be handled by hauler dwarves.\n"
- " autolabor disable\n"
- " Turn off autolabor for a specific labor.\n"
- " autolabor reset\n"
- " Return a labor to the default handling.\n"
- " autolabor reset-all\n"
- " Return all labors to the default handling.\n"
- " autolabor list\n"
- " List current status of all labors.\n"
- " autolabor status\n"
- " Show basic status information.\n"
- "Function:\n"
- " When enabled, autolabor periodically checks your dwarves and enables or\n"
- " disables labors. It tries to keep as many dwarves as possible busy but\n"
- " also tries to have dwarves specialize in specific skills.\n"
- " Warning: autolabor will override any manual changes you make to labors\n"
- " while it is enabled.\n"
- "Examples:\n"
- " autolabor MINE 2\n"
- " Keep at least 2 dwarves with mining enabled.\n"
- " autolabor CUT_GEM 1 1\n"
- " Keep exactly 1 dwarf with gemcutting enabled.\n"
- " autolabor FEED_WATER_CIVILIANS haulers\n"
- " Have haulers feed and water wounded dwarves.\n"
- " autolabor CUTWOOD disable\n"
- " Turn off autolabor for wood cutting.\n"
+ " autolabor disable\n"
+ " Enables or disables the plugin.\n"
+ " autolabor []\n"
+ " Set number of dwarves assigned to a labor.\n"
+ " autolabor haulers\n"
+ " Set a labor to be handled by hauler dwarves.\n"
+ " autolabor disable\n"
+ " Turn off autolabor for a specific labor.\n"
+ " autolabor reset\n"
+ " Return a labor to the default handling.\n"
+ " autolabor reset-all\n"
+ " Return all labors to the default handling.\n"
+ " autolabor list\n"
+ " List current status of all labors.\n"
+ " autolabor status\n"
+ " Show basic status information.\n"
+ "Function:\n"
+ " When enabled, autolabor periodically checks your dwarves and enables or\n"
+ " disables labors. It tries to keep as many dwarves as possible busy but\n"
+ " also tries to have dwarves specialize in specific skills.\n"
+ " Warning: autolabor will override any manual changes you make to labors\n"
+ " while it is enabled.\n"
+ "Examples:\n"
+ " autolabor MINE 2\n"
+ " Keep at least 2 dwarves with mining enabled.\n"
+ " autolabor CUT_GEM 1 1\n"
+ " Keep exactly 1 dwarf with gemcutting enabled.\n"
+ " autolabor FEED_WATER_CIVILIANS haulers\n"
+ " Have haulers feed and water wounded dwarves.\n"
+ " autolabor CUTWOOD disable\n"
+ " Turn off autolabor for wood cutting.\n"
));
- init_state();
+ init_state();
return CR_OK;
}
DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{
- cleanup_state();
+ cleanup_state();
- return CR_OK;
+ return CR_OK;
}
// sorting objects
@@ -704,7 +704,7 @@ DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_chan
DFhackCExport command_result plugin_onupdate ( color_ostream &out )
{
- static int step_count = 0;
+ static int step_count = 0;
// check run conditions
if(!world || !world->map.block_index || !enable_autolabor)
{
@@ -712,31 +712,31 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
return CR_OK;
}
- if (++step_count < 60)
- return CR_OK;
- step_count = 0;
+ if (++step_count < 60)
+ return CR_OK;
+ step_count = 0;
uint32_t race = ui->race_id;
uint32_t civ = ui->civ_id;
- std::vector dwarfs;
+ std::vector dwarfs;
- bool has_butchers = false;
- bool has_fishery = false;
+ bool has_butchers = false;
+ bool has_fishery = false;
bool trader_requested = false;
- for (int i = 0; i < world->buildings.all.size(); ++i)
- {
- df::building *build = world->buildings.all[i];
- auto type = build->getType();
- if (df::enums::building_type::Workshop == type)
- {
- auto subType = build->getSubtype();
- if (df::enums::workshop_type::Butchers == subType)
- has_butchers = true;
- if (df::enums::workshop_type::Fishery == subType)
- has_fishery = true;
- }
+ for (int i = 0; i < world->buildings.all.size(); ++i)
+ {
+ df::building *build = world->buildings.all[i];
+ auto type = build->getType();
+ if (df::enums::building_type::Workshop == type)
+ {
+ auto subType = build->getSubtype();
+ if (df::enums::workshop_type::Butchers == subType)
+ has_butchers = true;
+ if (df::enums::workshop_type::Fishery == subType)
+ has_fishery = true;
+ }
else if (df::enums::building_type::TradeDepot == type)
{
df::building_tradedepotst* depot = (df::building_tradedepotst*) build;
@@ -744,29 +744,29 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
if (print_debug)
out.print("Trade depot found and trader requested, trader will be excluded from all labors.\n");
}
- }
+ }
for (int i = 0; i < world->units.all.size(); ++i)
{
df::unit* cre = world->units.all[i];
- if (cre->race == race && cre->civ_id == civ && !cre->flags1.bits.marauder && !cre->flags1.bits.diplomat && !cre->flags1.bits.merchant &&
- !cre->flags1.bits.dead && !cre->flags1.bits.forest) {
- dwarfs.push_back(cre);
+ if (cre->race == race && cre->civ_id == civ && !cre->flags1.bits.marauder && !cre->flags1.bits.diplomat && !cre->flags1.bits.merchant &&
+ !cre->flags1.bits.dead && !cre->flags1.bits.forest) {
+ dwarfs.push_back(cre);
}
}
- int n_dwarfs = dwarfs.size();
+ int n_dwarfs = dwarfs.size();
- if (n_dwarfs == 0)
- return CR_OK;
+ if (n_dwarfs == 0)
+ return CR_OK;
- std::vector dwarf_info(n_dwarfs);
+ std::vector dwarf_info(n_dwarfs);
- // Find total skill and highest skill for each dwarf. More skilled dwarves shouldn't be used for minor tasks.
+ // Find total skill and highest skill for each dwarf. More skilled dwarves shouldn't be used for minor tasks.
- for (int dwarf = 0; dwarf < n_dwarfs; dwarf++)
- {
-// assert(dwarfs[dwarf]->status.souls.size() > 0);
+ for (int dwarf = 0; dwarf < n_dwarfs; dwarf++)
+ {
+// assert(dwarfs[dwarf]->status.souls.size() > 0);
// assert fails can cause DF to crash, so don't do that
if (dwarfs[dwarf]->status.souls.size() <= 0)
@@ -780,10 +780,10 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
for (int i = 0; i < hf->entity_links.size(); i++) {
df::histfig_entity_link* hfelink = hf->entity_links.at(i);
if (hfelink->getType() == df::histfig_entity_link_type::POSITION) {
- df::histfig_entity_link_positionst *epos =
+ df::histfig_entity_link_positionst *epos =
(df::histfig_entity_link_positionst*) hfelink;
df::historical_entity* entity = df::historical_entity::find(epos->entity_id);
- if (!entity)
+ if (!entity)
continue;
df::entity_position_assignment* assignment = binsearch_in_vector(entity->positions.assignments, epos->assignment_id);
if (!assignment)
@@ -792,8 +792,8 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
if (!position)
continue;
- for (int n = 0; n < 25; n++)
- if (position->responsibilities[n])
+ for (int n = 0; n < 25; n++)
+ if (position->responsibilities[n])
noble_penalty += responsibility_penalties[n];
if (position->responsibilities[df::entity_position_responsibility::HEALTH_MANAGEMENT])
@@ -806,420 +806,420 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
dwarf_info[dwarf].noble_penalty = noble_penalty;
}
- for (auto s = dwarfs[dwarf]->status.souls[0]->skills.begin(); s != dwarfs[dwarf]->status.souls[0]->skills.end(); s++)
- {
- df::job_skill skill = (*s)->id;
+ for (auto s = dwarfs[dwarf]->status.souls[0]->skills.begin(); s != dwarfs[dwarf]->status.souls[0]->skills.end(); s++)
+ {
+ df::job_skill skill = (*s)->id;
- df::job_skill_class skill_class = ENUM_ATTR(job_skill, type, skill);
+ df::job_skill_class skill_class = ENUM_ATTR(job_skill, type, skill);
- int skill_level = (*s)->rating;
- int skill_experience = (*s)->experience;
+ int skill_level = (*s)->rating;
+ int skill_experience = (*s)->experience;
- // Track total & highest skill among normal/medical skills. (We don't care about personal or social skills.)
+ // Track total & highest skill among normal/medical skills. (We don't care about personal or social skills.)
- if (skill_class != df::enums::job_skill_class::Normal && skill_class != df::enums::job_skill_class::Medical)
- continue;
+ if (skill_class != df::enums::job_skill_class::Normal && skill_class != df::enums::job_skill_class::Medical)
+ continue;
- if (dwarf_info[dwarf].highest_skill < skill_level)
- dwarf_info[dwarf].highest_skill = skill_level;
- dwarf_info[dwarf].total_skill += skill_level;
- }
- }
+ if (dwarf_info[dwarf].highest_skill < skill_level)
+ dwarf_info[dwarf].highest_skill = skill_level;
+ dwarf_info[dwarf].total_skill += skill_level;
+ }
+ }
- // Calculate a base penalty for using each dwarf for a task he isn't good at.
+ // Calculate a base penalty for using each dwarf for a task he isn't good at.
- for (int dwarf = 0; dwarf < n_dwarfs; dwarf++)
- {
- dwarf_info[dwarf].mastery_penalty -= 40 * dwarf_info[dwarf].highest_skill;
- dwarf_info[dwarf].mastery_penalty -= 10 * dwarf_info[dwarf].total_skill;
+ for (int dwarf = 0; dwarf < n_dwarfs; dwarf++)
+ {
+ dwarf_info[dwarf].mastery_penalty -= 40 * dwarf_info[dwarf].highest_skill;
+ dwarf_info[dwarf].mastery_penalty -= 10 * dwarf_info[dwarf].total_skill;
dwarf_info[dwarf].mastery_penalty -= dwarf_info[dwarf].noble_penalty;
- for (int labor = ENUM_FIRST_ITEM(unit_labor); labor <= ENUM_LAST_ITEM(unit_labor); labor++)
- {
- if (labor == df::enums::unit_labor::NONE)
- continue;
+ for (int labor = ENUM_FIRST_ITEM(unit_labor); labor <= ENUM_LAST_ITEM(unit_labor); labor++)
+ {
+ if (labor == df::enums::unit_labor::NONE)
+ continue;
/*
- assert(labor >= 0);
- assert(labor < ARRAY_COUNT(labor_infos));
- */
-
- if (labor_infos[labor].is_exclusive && dwarfs[dwarf]->status.labors[labor])
- dwarf_info[dwarf].mastery_penalty -= 100;
- }
- }
-
- // Find the activity state for each dwarf. It's important to get this right - a dwarf who we think is IDLE but
- // can't work will gum everything up. In the future I might add code to auto-detect slacker dwarves.
-
- state_count.clear();
- state_count.resize(NUM_STATE);
-
- for (int dwarf = 0; dwarf < n_dwarfs; dwarf++)
- {
- bool is_on_break = false;
-
- for (auto p = dwarfs[dwarf]->status.misc_traits.begin(); p < dwarfs[dwarf]->status.misc_traits.end(); p++)
- {
- // 7 / 0x7 = Newly arrived migrant, will not work yet
- // 17 / 0x11 = On break
- if ((*p)->id == 0x07 || (*p)->id == 0x11)
- is_on_break = true;
- }
-
- if (dwarfs[dwarf]->profession == df::enums::profession::BABY ||
- dwarfs[dwarf]->profession == df::enums::profession::CHILD ||
- dwarfs[dwarf]->profession == df::enums::profession::DRUNK)
- {
- dwarf_info[dwarf].state = CHILD;
- }
- else if (ENUM_ATTR(profession, military, dwarfs[dwarf]->profession))
- dwarf_info[dwarf].state = MILITARY;
- else if (dwarfs[dwarf]->job.current_job == NULL)
- {
- if (is_on_break)
- dwarf_info[dwarf].state = OTHER;
- else if (dwarfs[dwarf]->specific_refs.size() > 0)
- dwarf_info[dwarf].state = OTHER;
- else
- dwarf_info[dwarf].state = IDLE;
- }
- else
- {
- int job = dwarfs[dwarf]->job.current_job->job_type;
+ assert(labor >= 0);
+ assert(labor < ARRAY_COUNT(labor_infos));
+ */
+
+ if (labor_infos[labor].is_exclusive && dwarfs[dwarf]->status.labors[labor])
+ dwarf_info[dwarf].mastery_penalty -= 100;
+ }
+ }
+
+ // Find the activity state for each dwarf. It's important to get this right - a dwarf who we think is IDLE but
+ // can't work will gum everything up. In the future I might add code to auto-detect slacker dwarves.
+
+ state_count.clear();
+ state_count.resize(NUM_STATE);
+
+ for (int dwarf = 0; dwarf < n_dwarfs; dwarf++)
+ {
+ bool is_on_break = false;
+
+ for (auto p = dwarfs[dwarf]->status.misc_traits.begin(); p < dwarfs[dwarf]->status.misc_traits.end(); p++)
+ {
+ // 7 / 0x7 = Newly arrived migrant, will not work yet
+ // 17 / 0x11 = On break
+ if ((*p)->id == 0x07 || (*p)->id == 0x11)
+ is_on_break = true;
+ }
+
+ if (dwarfs[dwarf]->profession == df::enums::profession::BABY ||
+ dwarfs[dwarf]->profession == df::enums::profession::CHILD ||
+ dwarfs[dwarf]->profession == df::enums::profession::DRUNK)
+ {
+ dwarf_info[dwarf].state = CHILD;
+ }
+ else if (ENUM_ATTR(profession, military, dwarfs[dwarf]->profession))
+ dwarf_info[dwarf].state = MILITARY;
+ else if (dwarfs[dwarf]->job.current_job == NULL)
+ {
+ if (is_on_break)
+ dwarf_info[dwarf].state = OTHER;
+ else if (dwarfs[dwarf]->specific_refs.size() > 0)
+ dwarf_info[dwarf].state = OTHER;
+ else
+ dwarf_info[dwarf].state = IDLE;
+ }
+ else
+ {
+ int job = dwarfs[dwarf]->job.current_job->job_type;
/*
- assert(job >= 0);
- assert(job < ARRAY_COUNT(dwarf_states));
- */
+ assert(job >= 0);
+ assert(job < ARRAY_COUNT(dwarf_states));
+ */
if (job >= 0 && job < ARRAY_COUNT(dwarf_states))
dwarf_info[dwarf].state = dwarf_states[job];
- else
+ else
{
out.print("Dwarf %i \"%s\" has unknown job %i\n", dwarf, dwarfs[dwarf]->name.first_name.c_str(), job);
dwarf_info[dwarf].state = OTHER;
}
- }
+ }
- state_count[dwarf_info[dwarf].state]++;
+ state_count[dwarf_info[dwarf].state]++;
- if (print_debug)
- out.print("Dwarf %i \"%s\": penalty %i, state %s\n", dwarf, dwarfs[dwarf]->name.first_name.c_str(), dwarf_info[dwarf].mastery_penalty, state_names[dwarf_info[dwarf].state]);
- }
+ if (print_debug)
+ out.print("Dwarf %i \"%s\": penalty %i, state %s\n", dwarf, dwarfs[dwarf]->name.first_name.c_str(), dwarf_info[dwarf].mastery_penalty, state_names[dwarf_info[dwarf].state]);
+ }
- // Generate labor -> skill mapping
+ // Generate labor -> skill mapping
- df::job_skill labor_to_skill[ENUM_LAST_ITEM(unit_labor) + 1];
- for (int i = 0; i <= ENUM_LAST_ITEM(unit_labor); i++)
- labor_to_skill[i] = df::enums::job_skill::NONE;
+ df::job_skill labor_to_skill[ENUM_LAST_ITEM(unit_labor) + 1];
+ for (int i = 0; i <= ENUM_LAST_ITEM(unit_labor); i++)
+ labor_to_skill[i] = df::enums::job_skill::NONE;
- FOR_ENUM_ITEMS(job_skill, skill)
- {
- int labor = ENUM_ATTR(job_skill, labor, skill);
- if (labor != df::enums::unit_labor::NONE)
- {
+ FOR_ENUM_ITEMS(job_skill, skill)
+ {
+ int labor = ENUM_ATTR(job_skill, labor, skill);
+ if (labor != df::enums::unit_labor::NONE)
+ {
/*
- assert(labor >= 0);
- assert(labor < ARRAY_COUNT(labor_to_skill));
- */
+ assert(labor >= 0);
+ assert(labor < ARRAY_COUNT(labor_to_skill));
+ */
- labor_to_skill[labor] = skill;
- }
- }
+ labor_to_skill[labor] = skill;
+ }
+ }
- std::vector labors;
+ std::vector labors;
- FOR_ENUM_ITEMS(unit_labor, labor)
- {
- if (labor == df::enums::unit_labor::NONE)
- continue;
+ FOR_ENUM_ITEMS(unit_labor, labor)
+ {
+ if (labor == df::enums::unit_labor::NONE)
+ continue;
/*
- assert(labor >= 0);
- assert(labor < ARRAY_COUNT(labor_infos));
- */
+ assert(labor >= 0);
+ assert(labor < ARRAY_COUNT(labor_infos));
+ */
- labor_infos[labor].active_dwarfs = 0;
+ labor_infos[labor].active_dwarfs = 0;
- labors.push_back(labor);
- }
+ labors.push_back(labor);
+ }
laborinfo_sorter lasorter;
- std::sort(labors.begin(), labors.end(), lasorter);
+ std::sort(labors.begin(), labors.end(), lasorter);
- // Handle DISABLED skills (just bookkeeping)
- for (auto lp = labors.begin(); lp != labors.end(); ++lp)
- {
- auto labor = *lp;
+ // Handle DISABLED skills (just bookkeeping)
+ for (auto lp = labors.begin(); lp != labors.end(); ++lp)
+ {
+ auto labor = *lp;
- if (labor_infos[labor].mode() != DISABLE)
- continue;
+ if (labor_infos[labor].mode() != DISABLE)
+ continue;
- for (int dwarf = 0; dwarf < n_dwarfs; dwarf++)
- {
- if (dwarfs[dwarf]->status.labors[labor])
- {
- if (labor_infos[labor].is_exclusive)
- dwarf_info[dwarf].has_exclusive_labor = true;
+ for (int dwarf = 0; dwarf < n_dwarfs; dwarf++)
+ {
+ if (dwarfs[dwarf]->status.labors[labor])
+ {
+ if (labor_infos[labor].is_exclusive)
+ dwarf_info[dwarf].has_exclusive_labor = true;
- dwarf_info[dwarf].assigned_jobs++;
- }
- }
- }
+ dwarf_info[dwarf].assigned_jobs++;
+ }
+ }
+ }
- // Handle all skills except those marked HAULERS
+ // Handle all skills except those marked HAULERS
- for (auto lp = labors.begin(); lp != labors.end(); ++lp)
- {
- auto labor = *lp;
+ for (auto lp = labors.begin(); lp != labors.end(); ++lp)
+ {
+ auto labor = *lp;
/*
- assert(labor >= 0);
- assert(labor < ARRAY_COUNT(labor_infos));
- */
-
- df::job_skill skill = labor_to_skill[labor];
-
- if (labor_infos[labor].mode() != AUTOMATIC)
- continue;
-
- int best_dwarf = 0;
- int best_value = -10000;
-
- std::vector values(n_dwarfs);
- std::vector candidates;
- std::map dwarf_skill;
- std::vector previously_enabled(n_dwarfs);
-
- auto mode = labor_infos[labor].mode();
-
- // Find candidate dwarfs, and calculate a preference value for each dwarf
- for (int dwarf = 0; dwarf < n_dwarfs; dwarf++)
- {
- if (dwarf_info[dwarf].state == CHILD)
- continue;
- if (dwarf_info[dwarf].state == MILITARY)
- continue;
-
- if (labor_infos[labor].is_exclusive && dwarf_info[dwarf].has_exclusive_labor)
- continue;
-
- int value = dwarf_info[dwarf].mastery_penalty;
-
- if (skill != df::enums::job_skill::NONE)
- {
- int skill_level = 0;
- int skill_experience = 0;
-
- for (auto s = dwarfs[dwarf]->status.souls[0]->skills.begin(); s < dwarfs[dwarf]->status.souls[0]->skills.end(); s++)
- {
- if ((*s)->id == skill)
- {
- skill_level = (*s)->rating;
- skill_experience = (*s)->experience;
- break;
- }
- }
-
- dwarf_skill[dwarf] = skill_level;
-
- value += skill_level * 100;
- value += skill_experience / 20;
- if (skill_level > 0 || skill_experience > 0)
- value += 200;
- if (skill_level >= 15)
- value += 1000 * (skill_level - 14);
- }
- else
- {
- dwarf_skill[dwarf] = 0;
- }
-
- if (dwarfs[dwarf]->status.labors[labor])
- {
- value += 5;
- if (labor_infos[labor].is_exclusive)
- value += 350;
- }
-
- values[dwarf] = value;
-
- candidates.push_back(dwarf);
-
- }
-
- // Sort candidates by preference value
+ assert(labor >= 0);
+ assert(labor < ARRAY_COUNT(labor_infos));
+ */
+
+ df::job_skill skill = labor_to_skill[labor];
+
+ if (labor_infos[labor].mode() != AUTOMATIC)
+ continue;
+
+ int best_dwarf = 0;
+ int best_value = -10000;
+
+ std::vector values(n_dwarfs);
+ std::vector candidates;
+ std::map dwarf_skill;
+ std::vector previously_enabled(n_dwarfs);
+
+ auto mode = labor_infos[labor].mode();
+
+ // Find candidate dwarfs, and calculate a preference value for each dwarf
+ for (int dwarf = 0; dwarf < n_dwarfs; dwarf++)
+ {
+ if (dwarf_info[dwarf].state == CHILD)
+ continue;
+ if (dwarf_info[dwarf].state == MILITARY)
+ continue;
+
+ if (labor_infos[labor].is_exclusive && dwarf_info[dwarf].has_exclusive_labor)
+ continue;
+
+ int value = dwarf_info[dwarf].mastery_penalty;
+
+ if (skill != df::enums::job_skill::NONE)
+ {
+ int skill_level = 0;
+ int skill_experience = 0;
+
+ for (auto s = dwarfs[dwarf]->status.souls[0]->skills.begin(); s < dwarfs[dwarf]->status.souls[0]->skills.end(); s++)
+ {
+ if ((*s)->id == skill)
+ {
+ skill_level = (*s)->rating;
+ skill_experience = (*s)->experience;
+ break;
+ }
+ }
+
+ dwarf_skill[dwarf] = skill_level;
+
+ value += skill_level * 100;
+ value += skill_experience / 20;
+ if (skill_level > 0 || skill_experience > 0)
+ value += 200;
+ if (skill_level >= 15)
+ value += 1000 * (skill_level - 14);
+ }
+ else
+ {
+ dwarf_skill[dwarf] = 0;
+ }
+
+ if (dwarfs[dwarf]->status.labors[labor])
+ {
+ value += 5;
+ if (labor_infos[labor].is_exclusive)
+ value += 350;
+ }
+
+ values[dwarf] = value;
+
+ candidates.push_back(dwarf);
+
+ }
+
+ // Sort candidates by preference value
values_sorter ivs(values);
- std::sort(candidates.begin(), candidates.end(), ivs);
-
- // Disable the labor on everyone
- for (int dwarf = 0; dwarf < n_dwarfs; dwarf++)
- {
- if (dwarf_info[dwarf].state == CHILD)
- continue;
-
- previously_enabled[dwarf] = dwarfs[dwarf]->status.labors[labor];
- dwarfs[dwarf]->status.labors[labor] = false;
- }
-
- int min_dwarfs = labor_infos[labor].minimum_dwarfs();
- int max_dwarfs = labor_infos[labor].maximum_dwarfs();
-
- // Special - don't assign hunt without a butchers, or fish without a fishery
- if (df::enums::unit_labor::HUNT == labor && !has_butchers)
- min_dwarfs = max_dwarfs = 0;
- if (df::enums::unit_labor::FISH == labor && !has_fishery)
- min_dwarfs = max_dwarfs = 0;
-
- bool want_idle_dwarf = true;
- if (state_count[IDLE] < 2)
- want_idle_dwarf = false;
-
- /*
- * Assign dwarfs to this labor. We assign at least the minimum number of dwarfs, in
- * order of preference, and then assign additional dwarfs that meet any of these conditions:
- * - The dwarf is idle and there are no idle dwarves assigned to this labor
- * - The dwarf has nonzero skill associated with the labor
- * - The labor is mining, hunting, or woodcutting and the dwarf currently has it enabled.
- * We stop assigning dwarfs when we reach the maximum allowed.
- * Note that only idle and busy dwarfs count towards the number of dwarfs. "Other" dwarfs
- * (sleeping, eating, on break, etc.) will have labors assigned, but will not be counted.
- * Military and children/nobles will not have labors assigned.
+ std::sort(candidates.begin(), candidates.end(), ivs);
+
+ // Disable the labor on everyone
+ for (int dwarf = 0; dwarf < n_dwarfs; dwarf++)
+ {
+ if (dwarf_info[dwarf].state == CHILD)
+ continue;
+
+ previously_enabled[dwarf] = dwarfs[dwarf]->status.labors[labor];
+ dwarfs[dwarf]->status.labors[labor] = false;
+ }
+
+ int min_dwarfs = labor_infos[labor].minimum_dwarfs();
+ int max_dwarfs = labor_infos[labor].maximum_dwarfs();
+
+ // Special - don't assign hunt without a butchers, or fish without a fishery
+ if (df::enums::unit_labor::HUNT == labor && !has_butchers)
+ min_dwarfs = max_dwarfs = 0;
+ if (df::enums::unit_labor::FISH == labor && !has_fishery)
+ min_dwarfs = max_dwarfs = 0;
+
+ bool want_idle_dwarf = true;
+ if (state_count[IDLE] < 2)
+ want_idle_dwarf = false;
+
+ /*
+ * Assign dwarfs to this labor. We assign at least the minimum number of dwarfs, in
+ * order of preference, and then assign additional dwarfs that meet any of these conditions:
+ * - The dwarf is idle and there are no idle dwarves assigned to this labor
+ * - The dwarf has nonzero skill associated with the labor
+ * - The labor is mining, hunting, or woodcutting and the dwarf currently has it enabled.
+ * We stop assigning dwarfs when we reach the maximum allowed.
+ * Note that only idle and busy dwarfs count towards the number of dwarfs. "Other" dwarfs
+ * (sleeping, eating, on break, etc.) will have labors assigned, but will not be counted.
+ * Military and children/nobles will not have labors assigned.
* Dwarfs with the "health management" responsibility are always assigned DIAGNOSIS.
- */
- for (int i = 0; i < candidates.size() && labor_infos[labor].active_dwarfs < max_dwarfs; i++)
- {
- int dwarf = candidates[i];
-
- assert(dwarf >= 0);
- assert(dwarf < n_dwarfs);
-
- bool preferred_dwarf = false;
- if (want_idle_dwarf && dwarf_info[dwarf].state == IDLE)
- preferred_dwarf = true;
- if (dwarf_skill[dwarf] > 0)
- preferred_dwarf = true;
- if (previously_enabled[dwarf] && labor_infos[labor].is_exclusive)
- preferred_dwarf = true;
+ */
+ for (int i = 0; i < candidates.size() && labor_infos[labor].active_dwarfs < max_dwarfs; i++)
+ {
+ int dwarf = candidates[i];
+
+ assert(dwarf >= 0);
+ assert(dwarf < n_dwarfs);
+
+ bool preferred_dwarf = false;
+ if (want_idle_dwarf && dwarf_info[dwarf].state == IDLE)
+ preferred_dwarf = true;
+ if (dwarf_skill[dwarf] > 0)
+ preferred_dwarf = true;
+ if (previously_enabled[dwarf] && labor_infos[labor].is_exclusive)
+ preferred_dwarf = true;
if (dwarf_info[dwarf].medical && labor == df::unit_labor::DIAGNOSE)
preferred_dwarf = true;
if (dwarf_info[dwarf].trader && trader_requested)
continue;
- if (labor_infos[labor].active_dwarfs >= min_dwarfs && !preferred_dwarf)
- continue;
+ if (labor_infos[labor].active_dwarfs >= min_dwarfs && !preferred_dwarf)
+ continue;
- if (!dwarfs[dwarf]->status.labors[labor])
- dwarf_info[dwarf].assigned_jobs++;
+ if (!dwarfs[dwarf]->status.labors[labor])
+ dwarf_info[dwarf].assigned_jobs++;
- dwarfs[dwarf]->status.labors[labor] = true;
+ dwarfs[dwarf]->status.labors[labor] = true;
- if (labor_infos[labor].is_exclusive)
- {
- dwarf_info[dwarf].has_exclusive_labor = true;
- // all the exclusive labors require equipment so this should force the dorf to reequip if needed
- dwarfs[dwarf]->military.pickup_flags.bits.update = 1;
- }
+ if (labor_infos[labor].is_exclusive)
+ {
+ dwarf_info[dwarf].has_exclusive_labor = true;
+ // all the exclusive labors require equipment so this should force the dorf to reequip if needed
+ dwarfs[dwarf]->military.pickup_flags.bits.update = 1;
+ }
- if (print_debug)
- out.print("Dwarf %i \"%s\" assigned %s: value %i\n", dwarf, dwarfs[dwarf]->name.first_name.c_str(), ENUM_KEY_STR(unit_labor, labor).c_str(), values[dwarf]);
+ if (print_debug)
+ out.print("Dwarf %i \"%s\" assigned %s: value %i\n", dwarf, dwarfs[dwarf]->name.first_name.c_str(), ENUM_KEY_STR(unit_labor, labor).c_str(), values[dwarf]);
- if (dwarf_info[dwarf].state == IDLE || dwarf_info[dwarf].state == BUSY)
- labor_infos[labor].active_dwarfs++;
+ if (dwarf_info[dwarf].state == IDLE || dwarf_info[dwarf].state == BUSY)
+ labor_infos[labor].active_dwarfs++;
- if (dwarf_info[dwarf].state == IDLE)
- want_idle_dwarf = false;
- }
- }
+ if (dwarf_info[dwarf].state == IDLE)
+ want_idle_dwarf = false;
+ }
+ }
- // Set about 1/3 of the dwarfs as haulers. The haulers have all HAULER labors enabled. Having a lot of haulers helps
- // make sure that hauling jobs are handled quickly rather than building up.
+ // Set about 1/3 of the dwarfs as haulers. The haulers have all HAULER labors enabled. Having a lot of haulers helps
+ // make sure that hauling jobs are handled quickly rather than building up.
- int num_haulers = state_count[IDLE] + state_count[BUSY] / 3;
- if (num_haulers < 1)
- num_haulers = 1;
+ int num_haulers = state_count[IDLE] + state_count[BUSY] / 3;
+ if (num_haulers < 1)
+ num_haulers = 1;
- std::vector hauler_ids;
- for (int dwarf = 0; dwarf < n_dwarfs; dwarf++)
- {
+ std::vector hauler_ids;
+ for (int dwarf = 0; dwarf < n_dwarfs; dwarf++)
+ {
if (dwarf_info[dwarf].trader && trader_requested)
continue;
- if (dwarf_info[dwarf].state == IDLE || dwarf_info[dwarf].state == BUSY)
- hauler_ids.push_back(dwarf);
- }
+ if (dwarf_info[dwarf].state == IDLE || dwarf_info[dwarf].state == BUSY)
+ hauler_ids.push_back(dwarf);
+ }
dwarfinfo_sorter sorter(dwarf_info);
- // Idle dwarves come first, then we sort from least-skilled to most-skilled.
- std::sort(hauler_ids.begin(), hauler_ids.end(), sorter);
+ // Idle dwarves come first, then we sort from least-skilled to most-skilled.
+ std::sort(hauler_ids.begin(), hauler_ids.end(), sorter);
- // don't set any haulers if everyone is off drinking or something
- if (hauler_ids.size() == 0) {
- num_haulers = 0;
- }
+ // don't set any haulers if everyone is off drinking or something
+ if (hauler_ids.size() == 0) {
+ num_haulers = 0;
+ }
- FOR_ENUM_ITEMS(unit_labor, labor)
- {
- if (labor == df::enums::unit_labor::NONE)
- continue;
+ FOR_ENUM_ITEMS(unit_labor, labor)
+ {
+ if (labor == df::enums::unit_labor::NONE)
+ continue;
/*
- assert(labor >= 0);
- assert(labor < ARRAY_COUNT(labor_infos));
- */
+ assert(labor >= 0);
+ assert(labor < ARRAY_COUNT(labor_infos));
+ */
- if (labor_infos[labor].mode() != HAULERS)
- continue;
+ if (labor_infos[labor].mode() != HAULERS)
+ continue;
+
+ for (int i = 0; i < num_haulers; i++)
+ {
+ assert(i < hauler_ids.size());
- for (int i = 0; i < num_haulers; i++)
- {
- assert(i < hauler_ids.size());
+ int dwarf = hauler_ids[i];
- int dwarf = hauler_ids[i];
+ assert(dwarf >= 0);
+ assert(dwarf < n_dwarfs);
+ dwarfs[dwarf]->status.labors[labor] = true;
+ dwarf_info[dwarf].assigned_jobs++;
- assert(dwarf >= 0);
- assert(dwarf < n_dwarfs);
- dwarfs[dwarf]->status.labors[labor] = true;
- dwarf_info[dwarf].assigned_jobs++;
+ if (dwarf_info[dwarf].state == IDLE || dwarf_info[dwarf].state == BUSY)
+ labor_infos[labor].active_dwarfs++;
- if (dwarf_info[dwarf].state == IDLE || dwarf_info[dwarf].state == BUSY)
- labor_infos[labor].active_dwarfs++;
+ if (print_debug)
+ out.print("Dwarf %i \"%s\" assigned %s: hauler\n", dwarf, dwarfs[dwarf]->name.first_name.c_str(), ENUM_KEY_STR(unit_labor, labor).c_str());
+ }
- if (print_debug)
- out.print("Dwarf %i \"%s\" assigned %s: hauler\n", dwarf, dwarfs[dwarf]->name.first_name.c_str(), ENUM_KEY_STR(unit_labor, labor).c_str());
- }
+ for (int i = num_haulers; i < hauler_ids.size(); i++)
+ {
+ assert(i < hauler_ids.size());
- for (int i = num_haulers; i < hauler_ids.size(); i++)
- {
- assert(i < hauler_ids.size());
+ int dwarf = hauler_ids[i];
- int dwarf = hauler_ids[i];
-
- assert(dwarf >= 0);
- assert(dwarf < n_dwarfs);
+ assert(dwarf >= 0);
+ assert(dwarf < n_dwarfs);
- dwarfs[dwarf]->status.labors[labor] = false;
- }
- }
+ dwarfs[dwarf]->status.labors[labor] = false;
+ }
+ }
- print_debug = 0;
+ print_debug = 0;
return CR_OK;
}
void print_labor (df::enums::unit_labor::unit_labor labor, color_ostream &out)
{
- string labor_name = ENUM_KEY_STR(unit_labor, labor);
- out << labor_name << ": ";
- for (int i = 0; i < 20 - (int)labor_name.length(); i++)
- out << ' ';
- if (labor_infos[labor].mode() == DISABLE)
- out << "disabled" << endl;
- else
- {
- if (labor_infos[labor].mode() == HAULERS)
- out << "haulers";
- else
- out << "minimum " << labor_infos[labor].minimum_dwarfs() << ", maximum " << labor_infos[labor].maximum_dwarfs();
- out << ", currently " << labor_infos[labor].active_dwarfs << " dwarfs" << endl;
- }
+ string labor_name = ENUM_KEY_STR(unit_labor, labor);
+ out << labor_name << ": ";
+ for (int i = 0; i < 20 - (int)labor_name.length(); i++)
+ out << ' ';
+ if (labor_infos[labor].mode() == DISABLE)
+ out << "disabled" << endl;
+ else
+ {
+ if (labor_infos[labor].mode() == HAULERS)
+ out << "haulers";
+ else
+ out << "minimum " << labor_infos[labor].minimum_dwarfs() << ", maximum " << labor_infos[labor].maximum_dwarfs();
+ out << ", currently " << labor_infos[labor].active_dwarfs << " dwarfs" << endl;
+ }
}
command_result autolabor (color_ostream &out, std::vector & parameters)
@@ -1231,9 +1231,9 @@ command_result autolabor (color_ostream &out, std::vector & parame
return CR_FAILURE;
}
- if (parameters.size() == 1 &&
- (parameters[0] == "0" || parameters[0] == "enable" ||
- parameters[0] == "1" || parameters[0] == "disable"))
+ if (parameters.size() == 1 &&
+ (parameters[0] == "0" || parameters[0] == "enable" ||
+ parameters[0] == "1" || parameters[0] == "disable"))
{
bool enable = (parameters[0] == "1" || parameters[0] == "enable");
if (enable && !enable_autolabor)
@@ -1252,118 +1252,130 @@ command_result autolabor (color_ostream &out, std::vector & parame
return CR_OK;
}
- return CR_OK;
+ return CR_OK;
}
-
- if (!enable_autolabor)
- {
- out << "Error: The plugin is not enabled." << endl;
- return CR_FAILURE;
- }
-
- if (parameters.size() == 2 || parameters.size() == 3) {
- df::enums::unit_labor::unit_labor labor = df::enums::unit_labor::NONE;
-
- FOR_ENUM_ITEMS(unit_labor, test_labor)
- {
- if (parameters[0] == ENUM_KEY_STR(unit_labor, test_labor))
- labor = test_labor;
- }
-
- if (labor == df::enums::unit_labor::NONE)
- {
- out.printerr("Could not find labor %s.\n", parameters[0].c_str());
- return CR_WRONG_USAGE;
- }
-
- if (parameters[1] == "haulers")
- {
- labor_infos[labor].set_mode(HAULERS);
- print_labor(labor, out);
- return CR_OK;
- }
- if (parameters[1] == "disable")
- {
- labor_infos[labor].set_mode(DISABLE);
- print_labor(labor, out);
- return CR_OK;
- }
- if (parameters[1] == "reset")
- {
- reset_labor(labor);
- print_labor(labor, out);
- return CR_OK;
- }
-
- int minimum = atoi (parameters[1].c_str());
- int maximum = 200;
- if (parameters.size() == 3)
- maximum = atoi (parameters[2].c_str());
-
- if (maximum < minimum || maximum < 0 || minimum < 0)
- {
- out.printerr("Syntax: autolabor []\n", maximum, minimum);
- return CR_WRONG_USAGE;
- }
-
- labor_infos[labor].set_minimum_dwarfs(minimum);
- labor_infos[labor].set_maximum_dwarfs(maximum);
- labor_infos[labor].set_mode(AUTOMATIC);
- print_labor(labor, out);
-
- return CR_OK;
- }
- else if (parameters.size() == 1 && parameters[0] == "reset-all") {
- for (int i = 0; i < labor_infos.size(); i++)
- {
- reset_labor((df::enums::unit_labor::unit_labor) i);
- }
- out << "All labors reset." << endl;
- return CR_OK;
- }
- else if (parameters.size() == 1 && parameters[0] == "list" || parameters[0] == "status") {
- if (!enable_autolabor)
- {
- out << "autolabor not activated." << endl;
- return CR_OK;
- }
-
- bool need_comma = 0;
- for (int i = 0; i < NUM_STATE; i++)
- {
- if (state_count[i] == 0)
- continue;
- if (need_comma)
- out << ", ";
- out << state_count[i] << ' ' << state_names[i];
- need_comma = 1;
- }
- out << endl;
-
- if (parameters[0] == "list")
- {
- FOR_ENUM_ITEMS(unit_labor, labor)
- {
- if (labor == df::enums::unit_labor::NONE)
- continue;
-
- print_labor(labor, out);
- }
- }
-
- return CR_OK;
- }
- else if (parameters.size() == 1 && parameters[0] == "debug") {
- print_debug = 1;
-
- return CR_OK;
- }
- else
+
+ if (parameters.size() == 2 || parameters.size() == 3) {
+ if (!enable_autolabor)
+ {
+ out << "Error: The plugin is not enabled." << endl;
+ return CR_FAILURE;
+ }
+
+ df::enums::unit_labor::unit_labor labor = df::enums::unit_labor::NONE;
+
+ FOR_ENUM_ITEMS(unit_labor, test_labor)
+ {
+ if (parameters[0] == ENUM_KEY_STR(unit_labor, test_labor))
+ labor = test_labor;
+ }
+
+ if (labor == df::enums::unit_labor::NONE)
+ {
+ out.printerr("Could not find labor %s.\n", parameters[0].c_str());
+ return CR_WRONG_USAGE;
+ }
+
+ if (parameters[1] == "haulers")
+ {
+ labor_infos[labor].set_mode(HAULERS);
+ print_labor(labor, out);
+ return CR_OK;
+ }
+ if (parameters[1] == "disable")
+ {
+ labor_infos[labor].set_mode(DISABLE);
+ print_labor(labor, out);
+ return CR_OK;
+ }
+ if (parameters[1] == "reset")
+ {
+ reset_labor(labor);
+ print_labor(labor, out);
+ return CR_OK;
+ }
+
+ int minimum = atoi (parameters[1].c_str());
+ int maximum = 200;
+ if (parameters.size() == 3)
+ maximum = atoi (parameters[2].c_str());
+
+ if (maximum < minimum || maximum < 0 || minimum < 0)
+ {
+ out.printerr("Syntax: autolabor []\n", maximum, minimum);
+ return CR_WRONG_USAGE;
+ }
+
+ labor_infos[labor].set_minimum_dwarfs(minimum);
+ labor_infos[labor].set_maximum_dwarfs(maximum);
+ labor_infos[labor].set_mode(AUTOMATIC);
+ print_labor(labor, out);
+
+ return CR_OK;
+ }
+ else if (parameters.size() == 1 && parameters[0] == "reset-all") {
+ if (!enable_autolabor)
+ {
+ out << "Error: The plugin is not enabled." << endl;
+ return CR_FAILURE;
+ }
+
+ for (int i = 0; i < labor_infos.size(); i++)
+ {
+ reset_labor((df::enums::unit_labor::unit_labor) i);
+ }
+ out << "All labors reset." << endl;
+ return CR_OK;
+ }
+ else if (parameters.size() == 1 && parameters[0] == "list" || parameters[0] == "status") {
+ if (!enable_autolabor)
+ {
+ out << "Error: The plugin is not enabled." << endl;
+ return CR_FAILURE;
+ }
+
+ bool need_comma = 0;
+ for (int i = 0; i < NUM_STATE; i++)
+ {
+ if (state_count[i] == 0)
+ continue;
+ if (need_comma)
+ out << ", ";
+ out << state_count[i] << ' ' << state_names[i];
+ need_comma = 1;
+ }
+ out << endl;
+
+ if (parameters[0] == "list")
+ {
+ FOR_ENUM_ITEMS(unit_labor, labor)
+ {
+ if (labor == df::enums::unit_labor::NONE)
+ continue;
+
+ print_labor(labor, out);
+ }
+ }
+
+ return CR_OK;
+ }
+ else if (parameters.size() == 1 && parameters[0] == "debug") {
+ if (!enable_autolabor)
+ {
+ out << "Error: The plugin is not enabled." << endl;
+ return CR_FAILURE;
+ }
+
+ print_debug = 1;
+
+ return CR_OK;
+ }
+ else
{
out.print("Automatically assigns labors to dwarves.\n"
"Activate with 'autolabor 1', deactivate with 'autolabor 0'.\n"
"Current state: %d.\n", enable_autolabor);
- return CR_OK;
- }
+ return CR_OK;
+ }
}
From bf82b2d20dbb135dc81a877feb18cf456254b70b Mon Sep 17 00:00:00 2001
From: Quietust
Date: Tue, 17 Jul 2012 10:35:20 -0500
Subject: [PATCH 03/92] Sync with df-structures
---
library/modules/Buildings.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/library/modules/Buildings.cpp b/library/modules/Buildings.cpp
index e0afc56ed..8ec60e55b 100644
--- a/library/modules/Buildings.cpp
+++ b/library/modules/Buildings.cpp
@@ -991,7 +991,7 @@ bool Buildings::deconstruct(df::building *bld)
// Assume: no parties.
unlinkRooms(bld);
// Assume: not unit destroy target
- vector_erase_at(ui->unk8.unk10, linear_index(ui->unk8.unk10, bld));
+ vector_erase_at(ui->tax_collection.rooms, linear_index(ui->tax_collection.rooms, bld));
// Assume: not used in punishment
// Assume: not used in non-own jobs
// Assume: does not affect pathfinding
From 9f53f6296d77db6dace5a9d429b621513b0fe106 Mon Sep 17 00:00:00 2001
From: Warmist
Date: Wed, 18 Jul 2012 21:07:27 +0300
Subject: [PATCH 04/92] Removed Console module from dfusion.
---
plugins/Dfusion/dfusion.cpp | 3 -
plugins/Dfusion/include/lua_Console.h | 13 ---
plugins/Dfusion/luafiles/common.lua | 2 +-
plugins/Dfusion/luafiles/editor.lua | 2 +-
plugins/Dfusion/luafiles/init.lua | 10 +-
plugins/Dfusion/src/lua_Console.cpp | 131 --------------------------
6 files changed, 5 insertions(+), 156 deletions(-)
delete mode 100644 plugins/Dfusion/include/lua_Console.h
delete mode 100644 plugins/Dfusion/src/lua_Console.cpp
diff --git a/plugins/Dfusion/dfusion.cpp b/plugins/Dfusion/dfusion.cpp
index 2b36a9747..78c3fa8d1 100644
--- a/plugins/Dfusion/dfusion.cpp
+++ b/plugins/Dfusion/dfusion.cpp
@@ -1,5 +1,4 @@
#include "Core.h"
-#include "Console.h"
#include "Export.h"
#include "PluginManager.h"
#include "MemAccess.h"
@@ -12,7 +11,6 @@
#include "luamain.h"
-#include "lua_Console.h"
#include "lua_Process.h"
#include "lua_Hexsearch.h"
#include "lua_Misc.h"
@@ -50,7 +48,6 @@ DFhackCExport command_result plugin_init (color_ostream &out, std::vector
-#include "luamain.h"
-
-namespace lua
-{
-
-void RegisterConsole(lua::state &st);
-
-}
-
-#endif
\ No newline at end of file
diff --git a/plugins/Dfusion/luafiles/common.lua b/plugins/Dfusion/luafiles/common.lua
index 752d07cf6..7e621c4ea 100644
--- a/plugins/Dfusion/luafiles/common.lua
+++ b/plugins/Dfusion/luafiles/common.lua
@@ -8,7 +8,7 @@ DOUBLE=5
FLOAT=6
getline=function (inp)
-return Console.lineedit(inp or "")
+return dfhack.lineedit(inp or "")
end
io.stdin=nil
diff --git a/plugins/Dfusion/luafiles/editor.lua b/plugins/Dfusion/luafiles/editor.lua
index 1f004b2d5..06b07ce5e 100644
--- a/plugins/Dfusion/luafiles/editor.lua
+++ b/plugins/Dfusion/luafiles/editor.lua
@@ -127,7 +127,7 @@ function EditDF()
tbl[i]={k,getTypename(v)}
i=i+1
end
- number=Console.lineedit("select item to edit (q to quit):")
+ number=dfhack.lineedit("select item to edit (q to quit):")
if number and tonumber(number) then
local entry=tbl[tonumber(number)]
if entry==nil then
diff --git a/plugins/Dfusion/luafiles/init.lua b/plugins/Dfusion/luafiles/init.lua
index 6fa86d7ac..19f63d603 100644
--- a/plugins/Dfusion/luafiles/init.lua
+++ b/plugins/Dfusion/luafiles/init.lua
@@ -1,7 +1,3 @@
-Console.print = dfhack.print
-Console.println = dfhack.println
-Console.printerr = dfhack.printerr
-
function err(msg) --make local maybe...
print(msg)
print(debug.traceback())
@@ -30,13 +26,13 @@ function loadall(t1) --loads all non interactive plugin parts, so that later the
end
end
function mainmenu(t1)
- --Console.clear()
+
while true do
print("No. Name Desc")
for k,v in pairs(t1) do
print(string.format("%3d %15s %s",k,v[1],v[2]))
end
- local q=Console.lineedit("Select plugin to run (q to quit):")
+ local q=dfhack.lineedit("Select plugin to run (q to quit):")
if q=='q' then return end
q=tonumber(q)
if q~=nil then
@@ -92,7 +88,7 @@ local f,err=load(table.concat(args,' '))
if f then
f()
else
- Console.printerr(err)
+ dfhack.printerr(err)
end
if not INIT then
diff --git a/plugins/Dfusion/src/lua_Console.cpp b/plugins/Dfusion/src/lua_Console.cpp
deleted file mode 100644
index 1d52d6158..000000000
--- a/plugins/Dfusion/src/lua_Console.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-#include "LuaTools.h"
-
-#include "lua_Console.h"
-
-#include
-
-//TODO error management. Using lua error? or something other?
-static DFHack::color_ostream* GetConsolePtr(lua::state &st)
-{
- return DFHack::Lua::GetOutput(st);
-}
-
-static int lua_Console_clear(lua_State *S)
-{
- lua::state st(S);
- DFHack::color_ostream* c=GetConsolePtr(st);
- c->clear();
- return 0;
-}
-static int lua_Console_gotoxy(lua_State *S)
-{
- lua::state st(S);
- DFHack::color_ostream* c=GetConsolePtr(st);
- if(c->is_console())
- {
- DFHack::Console* con=static_cast(c);
- con->gotoxy(st.as(1,1),st.as(1,2));
- }
- return 0;
-}
-static int lua_Console_color(lua_State *S)
-{
- lua::state st(S);
- DFHack::color_ostream* c=GetConsolePtr(st);
- c->color( static_cast(st.as(-1,1)) );
- return 0;
-}
-static int lua_Console_reset_color(lua_State *S)
-{
- lua::state st(S);
- DFHack::color_ostream* c=GetConsolePtr(st);
- c->reset_color();
- return 0;
-}
-static int lua_Console_cursor(lua_State *S)
-{
- lua::state st(S);
- DFHack::color_ostream* c=GetConsolePtr(st);
- if(c->is_console())
- {
- DFHack::Console* con=static_cast(c);
- con->cursor(st.as(1));
- }
- return 0;
-}
-static int lua_Console_msleep(lua_State *S)
-{
- lua::state st(S);
- DFHack::color_ostream* c=GetConsolePtr(st);
- if(c->is_console())
- {
- DFHack::Console* con=static_cast(c);
- con->msleep(st.as(1));
- }
- return 0;
-}
-static int lua_Console_get_columns(lua_State *S)
-{
- lua::state st(S);
- DFHack::color_ostream* c=GetConsolePtr(st);
- if(c->is_console())
- {
- DFHack::Console* con=static_cast(c);
- st.push(con->get_columns());
- }
- return 1;
-}
-static int lua_Console_get_rows(lua_State *S)
-{
- lua::state st(S);
- DFHack::color_ostream* c=GetConsolePtr(st);
- if(c->is_console())
- {
- DFHack::Console* con=static_cast(c);
- st.push(con->get_rows());
- }
- return 1;
-}
-static int lua_Console_lineedit(lua_State *S)
-{
- lua::state st(S);
- DFHack::color_ostream* c=GetConsolePtr(st);
- if(c->is_console())
- {
- DFHack::Console* con=static_cast(c);
- string ret;
- DFHack::CommandHistory hist;
- int i=con->lineedit(st.as(1),ret,hist);
- st.push(ret);
- st.push(i);
- return 2;// dunno if len is needed...
- }
- else
- return 0;
-}
-const luaL_Reg lua_console_func[]=
-{
- {"clear",lua_Console_clear},
- {"gotoxy",lua_Console_gotoxy},
- {"color",lua_Console_color},
- {"reset_color",lua_Console_reset_color},
- {"cursor",lua_Console_cursor},
- {"msleep",lua_Console_msleep},
- {"get_columns",lua_Console_get_columns},
- {"get_rows",lua_Console_get_rows},
- {"lineedit",lua_Console_lineedit},
- {NULL,NULL}
-};
-void lua::RegisterConsole(lua::state &st)
-{
- st.getglobal("Console");
- if(st.is())
- {
- st.pop();
- st.newtable();
- }
-
- lua::RegFunctionsLocal(st, lua_console_func);
- //TODO add color consts
- st.setglobal("Console");
-}
From d8cb6e2c4edc62c2c1080103c8191f1cd6bc0ce5 Mon Sep 17 00:00:00 2001
From: Donald Ruegsegger
Date: Wed, 1 Aug 2012 19:52:50 -0500
Subject: [PATCH 05/92] Fixed seedwatch not working on reclaim
Just needed to add a check for game_type::DWARF_RECLAIM in two places
---
plugins/seedwatch.cpp | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/plugins/seedwatch.cpp b/plugins/seedwatch.cpp
index ae9ff0e14..676c02ed5 100755
--- a/plugins/seedwatch.cpp
+++ b/plugins/seedwatch.cpp
@@ -111,7 +111,8 @@ command_result df_seedwatch(color_ostream &out, vector& parameters)
w->ReadGameMode(gm);// FIXME: check return value
// if game mode isn't fortress mode
- if(gm.g_mode != game_mode::DWARF || gm.g_type != game_type::DWARF_MAIN)
+ if(gm.g_mode != game_mode::DWARF ||
+ !(gm.g_type == game_type::DWARF_MAIN || gm.g_type == game_type::DWARF_RECLAIM))
{
// just print the help
printHelp(out);
@@ -299,7 +300,8 @@ DFhackCExport command_result plugin_onupdate(color_ostream &out)
t_gamemodes gm;
w->ReadGameMode(gm);// FIXME: check return value
// if game mode isn't fortress mode
- if(gm.g_mode != game_mode::DWARF || gm.g_type != game_type::DWARF_MAIN)
+ if(gm.g_mode != game_mode::DWARF ||
+ !(gm.g_type == game_type::DWARF_MAIN || gm.g_type == game_type::DWARF_RECLAIM))
{
// stop running.
running = false;
From 589be93fbfc4710779720a6df997c6233d0b93d4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20Mr=C3=A1zek?=
Date: Thu, 2 Aug 2012 14:44:59 +0200
Subject: [PATCH 06/92] Sync with structures
---
library/xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/library/xml b/library/xml
index b646637f8..9f91e7476 160000
--- a/library/xml
+++ b/library/xml
@@ -1 +1 @@
-Subproject commit b646637f8eb901a95c82e60ccd4713e763e00179
+Subproject commit 9f91e74767b4d583b580d46e16143216ba62ae66
From 61195859e3544e17cd702676e6b7b8015684622a Mon Sep 17 00:00:00 2001
From: jj
Date: Fri, 3 Aug 2012 03:28:29 +0200
Subject: [PATCH 07/92] fix autolabor compilation error
---
plugins/autolabor.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/plugins/autolabor.cpp b/plugins/autolabor.cpp
index 7dbdedeb6..512899d75 100644
--- a/plugins/autolabor.cpp
+++ b/plugins/autolabor.cpp
@@ -96,7 +96,7 @@ command_result autolabor (color_ostream &out, std::vector & parame
// The name string provided must correspond to the filename - autolabor.plug.so or autolabor.plug.dll in this case
DFHACK_PLUGIN("autolabor");
-void generate_labor_to_skill_map();
+static void generate_labor_to_skill_map();
enum labor_mode {
DISABLE,
From 160487f7eb7fcc019644102f595a73e334f463d7 Mon Sep 17 00:00:00 2001
From: jj
Date: Fri, 3 Aug 2012 14:52:39 +0200
Subject: [PATCH 08/92] ruby: move all generated/downloaded stuff in the build/
directory
---
.gitignore | 6 ------
plugins/ruby/CMakeLists.txt | 24 +++++++++++++-----------
2 files changed, 13 insertions(+), 17 deletions(-)
diff --git a/.gitignore b/.gitignore
index 85fc083e7..bdb9474bb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -50,12 +50,6 @@ dfhack/python/PyDFHack.egg-info
dfhack/python/build
dfhack/python/dist
-# Ruby binding binaries
-plugins/ruby/libruby*
-plugins/ruby/msvcrtruby*.tar.gz
-plugins/ruby/ruby-autogen.rb
-plugins/ruby/ruby-autogen.rb.rule
-
# CPack stuff
build/CPack*Config.cmake
diff --git a/plugins/ruby/CMakeLists.txt b/plugins/ruby/CMakeLists.txt
index a9a85636c..0d9f1187d 100644
--- a/plugins/ruby/CMakeLists.txt
+++ b/plugins/ruby/CMakeLists.txt
@@ -1,29 +1,29 @@
OPTION(DL_RUBY "download libruby from the internet" ON)
IF (DL_RUBY AND NOT APPLE)
IF (UNIX)
- FILE(DOWNLOAD http://cloud.github.com/downloads/jjyg/dfhack/libruby187.tar.gz ${CMAKE_CURRENT_SOURCE_DIR}/libruby187.tar.gz
+ FILE(DOWNLOAD http://cloud.github.com/downloads/jjyg/dfhack/libruby187.tar.gz ${CMAKE_CURRENT_BINARY_DIR}/libruby187.tar.gz
EXPECTED_MD5 eb2adea59911f68e6066966c1352f291)
EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E tar xzf libruby187.tar.gz
- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
- FILE(RENAME libruby1.8.so.1.8.7 libruby.so)
- SET(RUBYLIB libruby.so)
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
+ FILE(RENAME ${CMAKE_CURRENT_BINARY_DIR}/libruby1.8.so.1.8.7 ${CMAKE_CURRENT_BINARY_DIR}/libruby.so)
+ SET(RUBYLIB ${CMAKE_CURRENT_BINARY_DIR}/libruby.so)
ELSE (UNIX)
- FILE(DOWNLOAD http://cloud.github.com/downloads/jjyg/dfhack/msvcrtruby187.tar.gz ${CMAKE_CURRENT_SOURCE_DIR}/msvcrtruby187.tar.gz
+ FILE(DOWNLOAD http://cloud.github.com/downloads/jjyg/dfhack/msvcrtruby187.tar.gz ${CMAKE_CURRENT_BINARY_DIR}/msvcrtruby187.tar.gz
EXPECTED_MD5 9f4a1659ac3a5308f32d3a1937bbeeae)
EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E tar xzf msvcrtruby187.tar.gz
- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
- FILE(RENAME msvcrt-ruby18.dll libruby.dll)
- SET(RUBYLIB libruby.dll)
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
+ FILE(RENAME ${CMAKE_CURRENT_BINARY_DIR}/msvcrt-ruby18.dll ${CMAKE_CURRENT_BINARY_DIR}/libruby.dll)
+ SET(RUBYLIB ${CMAKE_CURRENT_BINARY_DIR}/libruby.dll)
ENDIF(UNIX)
ENDIF(DL_RUBY AND NOT APPLE)
ADD_CUSTOM_COMMAND(
- OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/ruby-autogen.rb
- COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/codegen.pl ${dfhack_SOURCE_DIR}/library/include/df/codegen.out.xml ${CMAKE_CURRENT_SOURCE_DIR}/ruby-autogen.rb
+ OUTPUT ruby-autogen.rb
+ COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/codegen.pl ${dfhack_SOURCE_DIR}/library/include/df/codegen.out.xml ruby-autogen.rb
DEPENDS ${dfhack_SOURCE_DIR}/library/include/df/codegen.out.xml ${CMAKE_CURRENT_SOURCE_DIR}/codegen.pl
COMMENT ruby-autogen.rb
)
-ADD_CUSTOM_TARGET(ruby-autogen-rb DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/ruby-autogen.rb)
+ADD_CUSTOM_TARGET(ruby-autogen-rb DEPENDS ruby-autogen.rb)
INCLUDE_DIRECTORIES("${dfhack_SOURCE_DIR}/depends/tthread")
@@ -32,6 +32,8 @@ ADD_DEPENDENCIES(ruby ruby-autogen-rb)
INSTALL(FILES ${RUBYLIB} DESTINATION ${DFHACK_LIBRARY_DESTINATION})
+INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/ruby-autogen.rb DESTINATION hack/ruby)
+
INSTALL(DIRECTORY .
DESTINATION hack/ruby
FILES_MATCHING PATTERN "*.rb")
From 81ea0345ad8f9347ce6ef14bdd779ee1bef438a7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20Mr=C3=A1zek?=
Date: Fri, 3 Aug 2012 16:09:51 +0200
Subject: [PATCH 09/92] Fix cage-related bug in the sort plugin.
---
depends/clsocket | 2 +-
plugins/sort.cpp | 7 ++++++-
plugins/stonesense | 2 +-
3 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/depends/clsocket b/depends/clsocket
index c85e9fb35..d0b2d0750 160000
--- a/depends/clsocket
+++ b/depends/clsocket
@@ -1 +1 @@
-Subproject commit c85e9fb35d3510c5dcc367056cda3237d77a7add
+Subproject commit d0b2d0750dc2d529a152eba4f3f519f69ff7eab0
diff --git a/plugins/sort.cpp b/plugins/sort.cpp
index 5748a065b..ff51fc773 100644
--- a/plugins/sort.cpp
+++ b/plugins/sort.cpp
@@ -431,12 +431,17 @@ DEFINE_SORT_HANDLER(unit_sorters, dwarfmode, "/QueryBuilding/Some/Assign", scree
sort_null_first(parameters);
PARSE_SPEC("units", parameters);
-
if (compute_order(*pout, L, top, &order, *ui_building_assign_units))
{
reorder_cursor(ui_building_item_cursor, order);
reorder_vector(ui_building_assign_type, order);
reorder_vector(ui_building_assign_units, order);
+ // this is for cages. cages need some extra sorting
+ if(ui_building_assign_items->size() == ui_building_assign_units->size())
+ {
+ reorder_vector(ui_building_assign_items, order);
+ reorder_vector(ui_building_assign_is_marked, order);
+ }
}
}
diff --git a/plugins/stonesense b/plugins/stonesense
index 17b653665..5d4f06d78 160000
--- a/plugins/stonesense
+++ b/plugins/stonesense
@@ -1 +1 @@
-Subproject commit 17b653665567a5f1df628217820f76bb0b9c70a5
+Subproject commit 5d4f06d785f8a9933679fe3caa12c18215e9674d
From f400591080b29add7b64d196b4bf3911c2803ded Mon Sep 17 00:00:00 2001
From: jj
Date: Fri, 3 Aug 2012 16:53:54 +0200
Subject: [PATCH 10/92] ruby: use enums in single-bit values too
---
plugins/ruby/codegen.pl | 6 +++---
plugins/ruby/ruby-autogen-defs.rb | 10 +++++-----
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/plugins/ruby/codegen.pl b/plugins/ruby/codegen.pl
index cbe7c932a..593216d71 100755
--- a/plugins/ruby/codegen.pl
+++ b/plugins/ruby/codegen.pl
@@ -175,10 +175,10 @@ sub render_bitfield_fields {
if ($name)
{
- if ($count == 1) {
- push @lines_rb, "field(:$name, 0) { bit $shift }";
- } elsif ($enum) {
+ if ($enum) {
push @lines_rb, "field(:$name, 0) { bits $shift, $count, $enum }";
+ } elsif ($count == 1) {
+ push @lines_rb, "field(:$name, 0) { bit $shift }";
} else {
push @lines_rb, "field(:$name, 0) { bits $shift, $count }";
}
diff --git a/plugins/ruby/ruby-autogen-defs.rb b/plugins/ruby/ruby-autogen-defs.rb
index a1cba4168..2e4948acb 100644
--- a/plugins/ruby/ruby-autogen-defs.rb
+++ b/plugins/ruby/ruby-autogen-defs.rb
@@ -34,8 +34,8 @@ module DFHack
def float
Float.new
end
- def bit(shift)
- BitField.new(shift, 1)
+ def bit(shift, enum=nil)
+ BitField.new(shift, 1, enum)
end
def bits(shift, len, enum=nil)
BitField.new(shift, len, enum)
@@ -147,7 +147,7 @@ module DFHack
out << '>'
end
def inspect_field(n, o, s)
- if s.kind_of?(BitField) and s._len == 1
+ if s.kind_of?(BitField) and s._len == 1 and not s._enum
send(n) ? n.to_s : ''
elsif s.kind_of?(Pointer)
"#{n}=#{s._at(@_memaddr+o).inspect}"
@@ -242,7 +242,7 @@ module DFHack
def _get
v = DFHack.memory_read_int32(@_memaddr) >> @_shift
- if @_len == 1
+ if @_len == 1 and not @_enum
((v & 1) == 0) ? false : true
else
v &= _mask
@@ -252,7 +252,7 @@ module DFHack
end
def _set(v)
- if @_len == 1
+ if @_len == 1 and (not @_enum or v == false or v == true)
# allow 'bit = 0'
v = (v && v != 0 ? 1 : 0)
end
From c1bcd270e9488f668f0c38c4d8ac736f5368ee00 Mon Sep 17 00:00:00 2001
From: jj
Date: Fri, 3 Aug 2012 16:54:40 +0200
Subject: [PATCH 11/92] ruby: add spawn_water/spawn_magma methods to MapTile
---
plugins/ruby/map.rb | 48 ++++++++++++++++++++++++++++++++++++++++++
scripts/magmasource.rb | 16 +++-----------
2 files changed, 51 insertions(+), 13 deletions(-)
diff --git a/plugins/ruby/map.rb b/plugins/ruby/map.rb
index a0438670d..c99d5b88d 100644
--- a/plugins/ruby/map.rb
+++ b/plugins/ruby/map.rb
@@ -107,6 +107,31 @@ module DFHack
Tiletype::Direction[tiletype]
end
+ def shape_caption
+ TiletypeShape::Caption[shape]
+ end
+
+ def shape_basic
+ TiletypeShape::BasicShape[shape]
+ end
+
+ def shape_passablelow
+ TiletypeShape::PassableLow[shape]
+ end
+
+ def shape_passablehigh
+ TiletypeShape::PassableHigh[shape]
+ end
+
+ def shape_passableflow
+ TiletypeShape::PassableFlow[shape]
+ end
+
+ def shape_walkable
+ TiletypeShape::Walkable[shape]
+ end
+
+
# return all veins for current mapblock
def all_veins
mapblock.block_events.grep(BlockSquareEventMineralst)
@@ -162,5 +187,28 @@ module DFHack
def inspect
"#"
end
+
+ def spawn_liquid(quantity, is_magma=false, flowing=true)
+ designation.flow_size = quantity
+ designation.liquid_type = (is_magma ? :Magma : :Water)
+ designation.flow_forbid = true if is_magma or quantity >= 4
+
+ if flowing
+ mapblock.flags.update_liquid = true
+ mapblock.flags.update_liquid_twice = true
+
+ zf = df.world.map.z_level_flags[z]
+ zf.update = true
+ zf.update_twice = true
+ end
+ end
+
+ def spawn_water(quantity=7)
+ spawn_liquid(quantity)
+ end
+
+ def spawn_magma(quantity=7)
+ spawn_liquid(quantity, true)
+ end
end
end
diff --git a/scripts/magmasource.rb b/scripts/magmasource.rb
index 8525d51e0..e97080834 100644
--- a/scripts/magmasource.rb
+++ b/scripts/magmasource.rb
@@ -12,26 +12,16 @@ when 'here'
end
$magma_sources.each { |x, y, z|
- if tile = df.map_tile_at(x, y, z) and DFHack::TiletypeShape::PassableFlow[tile.shape]
+ if tile = df.map_tile_at(x, y, z) and tile.shape_passableflow
des = tile.designation
- des.flow_size += 1 if des.flow_size < 7
- des.liquid_type = 1
- des.flow_forbid = true
-
- mf = tile.mapblock.flags
- mf.update_liquid = true
- mf.update_liquid_twice = true
-
- zf = df.world.map.z_level_flags[z]
- zf.update = true
- zf.update_twice = true
+ tile.spawn_magma(des.flow_size + 1) if des.flow_size < 7
end
}
}
if df.cursor.x != -30000
if tile = df.map_tile_at(df.cursor)
- if DFHack::TiletypeShape::PassableFlow[tile.shape]
+ if tile.shape_passableflow
$magma_sources << [df.cursor.x, df.cursor.y, df.cursor.z]
else
puts "Impassable tile: I'm afraid I can't do that, Dave"
From 64a8443b5a3c467b3855ebdb2dd291ede5ca91f6 Mon Sep 17 00:00:00 2001
From: jj
Date: Fri, 3 Aug 2012 16:59:54 +0200
Subject: [PATCH 12/92] slayrace: add single-creature targetting, add magma
column mode
---
README.rst | 24 ++++++++++++++++++------
scripts/slayrace.rb | 32 +++++++++++++++++++++++++++++++-
2 files changed, 49 insertions(+), 7 deletions(-)
diff --git a/README.rst b/README.rst
index 724fa1fa3..6c463911a 100644
--- a/README.rst
+++ b/README.rst
@@ -1401,18 +1401,30 @@ Kills any unit of a given race.
With no argument, lists the available races.
+With the special argument 'him', targets only the selected creature.
+
Any non-dead non-caged unit of the specified race gets its ``blood_count``
-set to 0, which means immediate death at the next game tick. May not work
-on vampires and other weird creatures.
+set to 0, which means immediate death at the next game tick. For creatures
+such as vampires, also set animal.vanish_countdown to 2.
+
+An alternate mode is selected by adding a 2nd argument to the command,
+``magma``. In this case, a column of 7/7 magma is generated on top of the
+targets until they die (Warning: do not call on magma-safe creatures. Also,
+using this mode for birds is not recommanded.)
+
+Will target any unit on a revealed tile of the map, including ambushers.
-Targets any unit on a revealed tile of the map, including ambushers. Ex:
+Ex:
::
slayrace gob
-To kill a single creature in the same way, you can use the following line,
-after selecting the unit with the 'v' cursor:
+To kill a single creature, select the unit with the 'v' cursor and:
+::
+ slayrace him
+
+To purify all elves on the map with fire (may have side-effects):
::
- rb_eval df.unit_find.body.blood_count = 0
+ slayrace elve magma
magmasource
diff --git a/scripts/slayrace.rb b/scripts/slayrace.rb
index 27b1ba3cc..b1fc24e35 100644
--- a/scripts/slayrace.rb
+++ b/scripts/slayrace.rb
@@ -1,6 +1,9 @@
# slay all creatures of a given race
+# race = name of the race to eradicate, use 'him' to target only the selected creature
race = $script_args[0]
+# if the 2nd parameter is 'magma', magma rain for the targets instead of instant death
+magma = ($script_args[1] == 'magma')
checkunit = lambda { |u|
u.body.blood_count != 0 and
@@ -9,12 +12,39 @@ checkunit = lambda { |u|
not df.map_designation_at(u).hidden
}
+slayit = lambda { |u|
+ if not magma
+ # just make them drop dead
+ u.body.blood_count = 0
+ # some races dont mind having no blood, ensure they are still taken care of.
+ u.animal.vanish_countdown = 2
+ else
+ # it's getting hot around here
+ # !!WARNING!! do not call on a magma-safe creature
+ ouh = df.onupdate_register(1) {
+ if u.flags1.dead
+ df.onupdate_unregister(ouh)
+ else
+ x, y, z = u.pos.x, u.pos.y, u.pos.z
+ z += 1 while tile = df.map_tile_at(x, y, z+1) and tile.shape_passableflow
+ df.map_tile_at(x, y, z).spawn_magma(7)
+ end
+ }
+ end
+}
+
all_races = df.world.units.active.map { |u|
u.race_tg.creature_id if checkunit[u]
}.compact.uniq.sort
if !race
puts all_races
+elsif race == 'him'
+ if him = df.unit_find
+ slayit[him]
+ else
+ puts "Choose target"
+ end
else
raw_race = df.match_rawname(race, all_races)
raise 'invalid race' if not raw_race
@@ -24,7 +54,7 @@ else
count = 0
df.world.units.active.each { |u|
if u.race == race_nr and checkunit[u]
- u.body.blood_count = 0
+ slayit[u]
count += 1
end
}
From bb760bd376c0a0b4b622cbab0e1a7fca40598ed9 Mon Sep 17 00:00:00 2001
From: Valentin Ochs
Date: Mon, 6 Aug 2012 16:55:55 +0200
Subject: [PATCH 13/92] Added quality constraints to workflow plugin
---
plugins/workflow.cpp | 35 ++++++++++++++++++++++++++++++-----
1 file changed, 30 insertions(+), 5 deletions(-)
diff --git a/plugins/workflow.cpp b/plugins/workflow.cpp
index dbf546070..c2875a1b8 100644
--- a/plugins/workflow.cpp
+++ b/plugins/workflow.cpp
@@ -20,6 +20,7 @@
#include "df/job_list_link.h"
#include "df/dfhack_material_category.h"
#include "df/item.h"
+#include "df/item_quality.h"
#include "df/items_other_id.h"
#include "df/tool_uses.h"
#include "df/general_ref.h"
@@ -42,6 +43,7 @@ using std::string;
using std::endl;
using namespace DFHack;
using namespace df::enums;
+using namespace df::enums::item_quality;
using df::global::world;
using df::global::ui;
@@ -283,6 +285,8 @@ struct ItemConstraint {
int weight;
std::vector jobs;
+ enum item_quality min_quality;
+
int item_amount, item_count, item_inuse;
bool request_suspend, request_resume;
@@ -293,7 +297,7 @@ struct ItemConstraint {
public:
ItemConstraint()
: is_craft(false), weight(0), item_amount(0), item_count(0), item_inuse(0)
- , is_active(false), cant_resume_reported(false)
+ , is_active(false), cant_resume_reported(false), min_quality(Ordinary)
{}
int goalCount() { return config.ival(0); }
@@ -646,7 +650,7 @@ static ItemConstraint *get_constraint(color_ostream &out, const std::string &str
std::vector tokens;
split_string(&tokens, str, "/");
- if (tokens.size() > 3)
+ if (tokens.size() > 4)
return NULL;
int weight = 0;
@@ -670,10 +674,10 @@ static ItemConstraint *get_constraint(color_ostream &out, const std::string &str
out.printerr("Cannot decode material mask: %s\n", maskstr.c_str());
return NULL;
}
-
+
if (mat_mask.whole != 0)
weight += 100;
-
+
MaterialInfo material;
std::string matstr = vector_get(tokens,2);
if (!matstr.empty() && (!material.find(matstr) || !material.isValid())) {
@@ -681,6 +685,22 @@ static ItemConstraint *get_constraint(color_ostream &out, const std::string &str
return NULL;
}
+ enum item_quality minqual = Ordinary;
+ std::string qualstr = vector_get(tokens, 3);
+ if(!qualstr.empty()) {
+ if(qualstr == "ordinary") minqual = Ordinary;
+ else if(qualstr == "wellcrafted") minqual = WellCrafted;
+ else if(qualstr == "finelycrafted") minqual = FinelyCrafted;
+ else if(qualstr == "superior") minqual = Superior;
+ else if(qualstr == "exceptional") minqual = Exceptional;
+ else if(qualstr == "masterful") minqual = Masterful;
+ else {
+ out.printerr("Cannot find quality: %s\nKnown qualities: ordinary, wellcrafted, finelycrafted, superior, exceptional, masterful\n", qualstr.c_str());
+ return NULL;
+ }
+
+ }
+
if (material.type >= 0)
weight += (material.index >= 0 ? 5000 : 1000);
@@ -694,7 +714,8 @@ static ItemConstraint *get_constraint(color_ostream &out, const std::string &str
ItemConstraint *ct = constraints[i];
if (ct->is_craft == is_craft &&
ct->item == item && ct->material == material &&
- ct->mat_mask.whole == mat_mask.whole)
+ ct->mat_mask.whole == mat_mask.whole &&
+ ct->min_quality == minqual)
return ct;
}
@@ -703,6 +724,7 @@ static ItemConstraint *get_constraint(color_ostream &out, const std::string &str
nct->item = item;
nct->material = material;
nct->mat_mask = mat_mask;
+ nct->min_quality = minqual;
nct->weight = weight;
if (cfg)
@@ -1179,6 +1201,9 @@ static void map_job_items(color_ostream &out)
(cv->item.subtype != -1 && cv->item.subtype != isubtype))
continue;
}
+ if(item->getQuality() < cv->min_quality) {
+ continue;
+ }
TMaterialCache::iterator it = cv->material_cache.find(matkey);
From 2c703ffbca9bac26ba64aad7484e012da451ff52 Mon Sep 17 00:00:00 2001
From: Valentin Ochs
Date: Mon, 6 Aug 2012 16:59:09 +0200
Subject: [PATCH 14/92] Remove unnecessary whitespace
---
plugins/workflow.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/plugins/workflow.cpp b/plugins/workflow.cpp
index c2875a1b8..0b87b3590 100644
--- a/plugins/workflow.cpp
+++ b/plugins/workflow.cpp
@@ -698,7 +698,6 @@ static ItemConstraint *get_constraint(color_ostream &out, const std::string &str
out.printerr("Cannot find quality: %s\nKnown qualities: ordinary, wellcrafted, finelycrafted, superior, exceptional, masterful\n", qualstr.c_str());
return NULL;
}
-
}
if (material.type >= 0)
From 4039d2c0b7cddf458cb5ad4afc006ab66371416d Mon Sep 17 00:00:00 2001
From: Valentin Ochs
Date: Wed, 8 Aug 2012 10:47:02 +0200
Subject: [PATCH 15/92] Don't disable autolabor when you input "autolabor
1|enable" and it's already enabled.
---
plugins/autolabor.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/plugins/autolabor.cpp b/plugins/autolabor.cpp
index 512899d75..d23c66925 100644
--- a/plugins/autolabor.cpp
+++ b/plugins/autolabor.cpp
@@ -1348,7 +1348,7 @@ command_result autolabor (color_ostream &out, std::vector & parame
{
enable_plugin(out);
}
- else
+ else if(!enable)
{
if (enable_autolabor)
{
From 2abb9a898ca86c301db626db227714073e61a3a3 Mon Sep 17 00:00:00 2001
From: Valentin Ochs
Date: Wed, 8 Aug 2012 10:50:07 +0200
Subject: [PATCH 16/92] One more autolabor cleanup
---
plugins/autolabor.cpp | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/plugins/autolabor.cpp b/plugins/autolabor.cpp
index d23c66925..c3a2b313e 100644
--- a/plugins/autolabor.cpp
+++ b/plugins/autolabor.cpp
@@ -1348,16 +1348,12 @@ command_result autolabor (color_ostream &out, std::vector & parame
{
enable_plugin(out);
}
- else if(!enable)
+ else if(!enable && enable_autolabor)
{
- if (enable_autolabor)
- {
- enable_autolabor = false;
- setOptionEnabled(CF_ENABLED, false);
- }
+ enable_autolabor = false;
+ setOptionEnabled(CF_ENABLED, false);
out << "The plugin is disabled." << endl;
- return CR_OK;
}
return CR_OK;
From 7a03f93dbd4f1a3af2d8c367b4cba22d675d2a82 Mon Sep 17 00:00:00 2001
From: jj
Date: Thu, 9 Aug 2012 14:40:14 +0200
Subject: [PATCH 17/92] ruby: add raw stl::string allocation, add _cpp_delete,
tweak readme
---
plugins/ruby/README | 48 ++++++++++++++----
plugins/ruby/ruby-autogen-defs.rb | 62 +++++++++++++++++++----
plugins/ruby/ruby.cpp | 83 ++++++++++++++++++++++++-------
3 files changed, 155 insertions(+), 38 deletions(-)
diff --git a/plugins/ruby/README b/plugins/ruby/README
index 97a4cbd30..8a473f332 100644
--- a/plugins/ruby/README
+++ b/plugins/ruby/README
@@ -23,7 +23,7 @@ All ruby code runs while the main DF process and other plugins are suspended.
DFHack console
--------------
-The ruby plugin defines 1 dfhack console command:
+The ruby plugin defines one new dfhack console command:
rb_eval ; evaluate a ruby expression and show the result in
the console. Ex: rb_eval df.unit_find().name.first_name
You can use single-quotes for strings ; avoid double-quotes that are parsed
@@ -50,7 +50,7 @@ The script can access the console command arguments through the global variable
'$script_args', which is an array of ruby Strings.
The help string displayed in dfhack 'ls' command is the first line of the
-script, if it is a comment (starts with '# ').
+script, if it is a comment (ie starts with '# ').
Ruby helper functions
@@ -67,7 +67,9 @@ obj1 and 2 should respond to #pos and #x #y #z.
Returns the MapBlock for the coordinates or nil.
df.map_tile_at(pos)
-Returns a MapTile, holds all information relative to the map tile.
+Returns a MapTile, holding all informations wrt the map tile (read&write).
+This class is a ruby specific extention, to facilitate interaction with the
+DF map data. Check out hack/ruby/map.rb.
df.each_map_block { |b| }
df.each_map_block_z(zlevel) { |b| }
@@ -142,9 +144,16 @@ The ruby classes defined in ruby-autogen.rb are accessors to the underlying
df C++ objects in-memory. To allocate a new C++ object for use in DF, use the
RubyClass.cpp_new method (see buildings.rb for exemples), works for Compounds
only.
+A special Compound DFHack::StlString is available for allocating a single c++
+stl::string, so that you can call vmethods that take a string pointer argument
+(eg getName).
+ ex: s = DFHack::StlString.cpp_new ; df.building_find.getName(s) ; p s.str
-Deallocation is not supported. You may manually call df.free if you know
-what you are doing (maps directly to the native malloc/free)
+Deallocation may work, using the compound method _cpp_delete. Use with caution,
+may crash your DF session. It may be simpler to just leak the memory.
+_cpp_delete will try to free all memory directly used by the compound, eg
+strings and vectors. It will *not* call the class destructor, and will not free
+stuff behind pointers.
C++ std::string fields may be directly re-allocated using standard ruby strings,
e.g. some_unit.name.nickname = 'moo'
@@ -160,11 +169,13 @@ To delete an element, vector.delete_at(index)
You can binary search an element in a vector for a given numeric field value:
df.world.unit.all.binsearch(42, :id)
-will find the element whose 'id' field is 42 (needs the vector to be initially
+will find the entry whose 'id' field is 42 (needs the vector to be initially
sorted by this field). The binsearch 2nd argument defaults to :id.
Any numeric field defined as being an enum value will be converted to a ruby
Symbol. This works for array indexes too.
+ ex: df.unit_find(:selected).status.labors[:HAUL_FOOD] = true
+ df.map_tile_at(df.cursor).designation.liquid_type = :Water
Virtual method calls are supported for C++ objects, with a maximum of 4
arguments. Arguments / return value are interpreted as Compound/Enums as
@@ -194,7 +205,7 @@ Change current unit profession
Center the screen on unit ID '123'
df.center_viewscreen(df.unit_find(123))
-Find an item at a given position, show its C++ classname
+Find an item under the game cursor and show its C++ classname
p df.item_find(df.cursor)._rtti_classname
Find the raws name of the plant under cursor
@@ -205,15 +216,29 @@ Dig a channel under the cursor
df.map_designation_at(df.cursor).dig = :Channel
df.map_block_at(df.cursor).flags.designated = true
+Spawn 2/7 magma on the tile of the dwarf nicknamed 'hotfeet'
+ hot = df.unit_citizens.find { |u| u.name.nickname == 'hotfeet' }
+ df.map_tile_at(hot).spawn_magma(2)
+
Plugin compilation
------------------
-The plugin consists of the *.rb file including user comfort functions and
-describing basic classes used by the autogenerated code, and ruby-autogen.rb,
-the auto-generated code.
+The plugin consists of the main ruby.cpp native plugin and the *.rb files.
+
+The native plugin handles only low-level ruby-to-df interaction (eg raw memory
+read/write, and dfhack integration), and the .rb files hold end-user helper
+functions.
+
+On dfhack start, the native plugin will initialize the ruby interpreter, and
+load hack/ruby/ruby.rb. This one then loads all other .rb files.
-autogen is output by codegen.pl from dfhack/library/include/df/codegen.out.xml
+The DF internal structures are described in ruby-autogen.rb .
+It is output by ruby/codegen.pl, from dfhack/library/include/df/codegen.out.xml
+It contains architecture-specific data (eg DF internal structures field offsets,
+which differ between Windows and Linux. Linux and Macosx are the same, as they
+both use gcc).
+It is stored inside the build directory (eg build/plugins/ruby/ruby-autogen.rb)
For exemple,
@@ -230,6 +255,7 @@ Will generate
The syntax for the 'field' method in ruby-autogen.rb is:
1st argument = name of the method
2nd argument = offset of this field from the beginning of the current struct.
+ This field depends on the compiler used by Toady to generate DF.
The block argument describes the type of the field: uint32, ptr to global...
Primitive type access is done through native methods from ruby.cpp (vector length,
diff --git a/plugins/ruby/ruby-autogen-defs.rb b/plugins/ruby/ruby-autogen-defs.rb
index 2e4948acb..7165e2448 100644
--- a/plugins/ruby/ruby-autogen-defs.rb
+++ b/plugins/ruby/ruby-autogen-defs.rb
@@ -7,6 +7,7 @@ module DFHack
def _at(addr) ; d = dup ; d._memaddr = addr ; d ; end
def _get ; self ; end
def _cpp_init ; end
+ def _cpp_delete ; end
end
class Compound < MemStruct
@@ -114,6 +115,11 @@ module DFHack
def _cpp_init
_fields_ancestors.each { |n, o, s| s._at(@_memaddr+o)._cpp_init }
end
+ def _cpp_delete
+ _fields_ancestors.each { |n, o, s| s._at(@_memaddr+o)._cpp_delete }
+ DFHack.free(@_memaddr)
+ @_memaddr = nil # turn future segfaults in harmless ruby exceptions
+ end
def _set(h)
case h
when Hash; h.each { |k, v| send("#{k}=", v) }
@@ -372,6 +378,9 @@ module DFHack
def _cpp_init
_length.times { |i| _tgat(i)._cpp_init }
end
+ def _cpp_delete
+ _length.times { |i| _tgat(i)._cpp_delete }
+ end
alias length _length
alias size _length
def _tgat(i)
@@ -423,10 +432,10 @@ module DFHack
DFHack.memory_vector32_ptrat(@_memaddr, idx)
end
def insert_at(idx, val)
- DFHack.memory_vector32_insert(@_memaddr, idx, val)
+ DFHack.memory_vector32_insertat(@_memaddr, idx, val)
end
def delete_at(idx)
- DFHack.memory_vector32_delete(@_memaddr, idx)
+ DFHack.memory_vector32_deleteat(@_memaddr, idx)
end
def _set(v)
@@ -434,6 +443,12 @@ module DFHack
v.each_with_index { |e, i| self[i] = e } # patch entries
end
+ def self._cpp_new
+ new._at DFHack.memory_vector_new
+ end
+ def _cpp_delete
+ DFHack.memory_vector_delete(@_memaddr)
+ end
def _cpp_init
DFHack.memory_vector_init(@_memaddr)
end
@@ -496,10 +511,10 @@ module DFHack
DFHack.memory_vector16_ptrat(@_memaddr, idx)
end
def insert_at(idx, val)
- DFHack.memory_vector16_insert(@_memaddr, idx, val)
+ DFHack.memory_vector16_insertat(@_memaddr, idx, val)
end
def delete_at(idx)
- DFHack.memory_vector16_delete(@_memaddr, idx)
+ DFHack.memory_vector16_deleteat(@_memaddr, idx)
end
end
class StlVector8 < StlVector32
@@ -510,10 +525,10 @@ module DFHack
DFHack.memory_vector8_ptrat(@_memaddr, idx)
end
def insert_at(idx, val)
- DFHack.memory_vector8_insert(@_memaddr, idx, val)
+ DFHack.memory_vector8_insertat(@_memaddr, idx, val)
end
def delete_at(idx)
- DFHack.memory_vector8_delete(@_memaddr, idx)
+ DFHack.memory_vector8_deleteat(@_memaddr, idx)
end
end
class StlBitVector < StlVector32
@@ -522,10 +537,10 @@ module DFHack
DFHack.memory_vectorbool_length(@_memaddr)
end
def insert_at(idx, val)
- DFHack.memory_vectorbool_insert(@_memaddr, idx, val)
+ DFHack.memory_vectorbool_insertat(@_memaddr, idx, val)
end
def delete_at(idx)
- DFHack.memory_vectorbool_delete(@_memaddr, idx)
+ DFHack.memory_vectorbool_deleteat(@_memaddr, idx)
end
def [](idx)
idx += length if idx < 0
@@ -541,6 +556,12 @@ module DFHack
DFHack.memory_vectorbool_setat(@_memaddr, idx, v)
end
end
+ def self._cpp_new
+ new._at DFHack.memory_vectorbool_new
+ end
+ def _cpp_delete
+ DFHack.memory_vectorbool_delete(@_memaddr)
+ end
end
class StlString < MemStruct
def _get
@@ -551,6 +572,12 @@ module DFHack
DFHack.memory_write_stlstring(@_memaddr, v)
end
+ def self._cpp_new
+ new._at DFHack.memory_stlstring_new
+ end
+ def _cpp_delete
+ DFHack.memory_stlstring_delete(@_memaddr)
+ end
def _cpp_init
DFHack.memory_stlstring_init(@_memaddr)
end
@@ -574,7 +601,7 @@ module DFHack
def length
DFHack.memory_bitarray_length(@_memaddr)
end
- # TODO _cpp_init
+ # TODO _cpp_init, _cpp_delete
def size ; length ; end
def resize(len)
DFHack.memory_bitarray_resize(@_memaddr, len)
@@ -608,7 +635,7 @@ module DFHack
def length ; _length ; end
def size ; _length ; end
- # TODO _cpp_init
+ # TODO _cpp_init, _cpp_delete
def _tgat(i)
@_tg._at(_ptr + i*@_tglen) if i >= 0 and i < _length
end
@@ -702,6 +729,21 @@ module DFHack
def self.sym(v) ; (!v || (v == 0)) ? false : true ; end
end
+ class StlString < MemHack::Compound
+ field(:str, 0) { stl_string }
+
+ def self.cpp_new(init=nil)
+ s = MemHack::StlString._cpp_new
+ s._set(init) if init
+ new._at(s._memaddr)
+ end
+
+ def _cpp_delete
+ MemHack::StlString.new._at(@_memaddr+0)._cpp_delete
+ @_memaddr = nil
+ end
+ end
+
# cpp rtti name -> rb class
@rtti_n2c = {}
@rtti_c2n = {}
diff --git a/plugins/ruby/ruby.cpp b/plugins/ruby/ruby.cpp
index 08ea13b9f..1391faa44 100644
--- a/plugins/ruby/ruby.cpp
+++ b/plugins/ruby/ruby.cpp
@@ -528,7 +528,7 @@ static VALUE rb_dfmalloc(VALUE self, VALUE len)
if (!ptr)
return Qnil;
memset(ptr, 0, FIX2INT(len));
- return rb_uint2inum((long)ptr);
+ return rb_uint2inum((uint32_t)ptr);
}
static VALUE rb_dffree(VALUE self, VALUE ptr)
@@ -599,6 +599,18 @@ static VALUE rb_dfmemory_write_float(VALUE self, VALUE addr, VALUE val)
// stl::string
+static VALUE rb_dfmemory_stlstring_new(VALUE self)
+{
+ std::string *ptr = new std::string;
+ return rb_uint2inum((uint32_t)ptr);
+}
+static VALUE rb_dfmemory_stlstring_delete(VALUE self, VALUE addr)
+{
+ std::string *ptr = (std::string*)rb_num2ulong(addr);
+ if (ptr)
+ delete ptr;
+ return Qtrue;
+}
static VALUE rb_dfmemory_stlstring_init(VALUE self, VALUE addr)
{
// XXX THIS IS TERRIBLE
@@ -621,6 +633,18 @@ static VALUE rb_dfmemory_write_stlstring(VALUE self, VALUE addr, VALUE val)
// vector access
+static VALUE rb_dfmemory_vec_new(VALUE self)
+{
+ std::vector *ptr = new std::vector;
+ return rb_uint2inum((uint32_t)ptr);
+}
+static VALUE rb_dfmemory_vec_delete(VALUE self, VALUE addr)
+{
+ std::vector *ptr = (std::vector*)rb_num2ulong(addr);
+ if (ptr)
+ delete ptr;
+ return Qtrue;
+}
static VALUE rb_dfmemory_vec_init(VALUE self, VALUE addr)
{
std::vector *ptr = new std::vector;
@@ -638,13 +662,13 @@ static VALUE rb_dfmemory_vec8_ptrat(VALUE self, VALUE addr, VALUE idx)
std::vector *v = (std::vector*)rb_num2ulong(addr);
return rb_uint2inum((uint32_t)&v->at(FIX2INT(idx)));
}
-static VALUE rb_dfmemory_vec8_insert(VALUE self, VALUE addr, VALUE idx, VALUE val)
+static VALUE rb_dfmemory_vec8_insertat(VALUE self, VALUE addr, VALUE idx, VALUE val)
{
std::vector *v = (std::vector*)rb_num2ulong(addr);
v->insert(v->begin()+FIX2INT(idx), rb_num2ulong(val));
return Qtrue;
}
-static VALUE rb_dfmemory_vec8_delete(VALUE self, VALUE addr, VALUE idx)
+static VALUE rb_dfmemory_vec8_deleteat(VALUE self, VALUE addr, VALUE idx)
{
std::vector *v = (std::vector*)rb_num2ulong(addr);
v->erase(v->begin()+FIX2INT(idx));
@@ -662,13 +686,13 @@ static VALUE rb_dfmemory_vec16_ptrat(VALUE self, VALUE addr, VALUE idx)
std::vector *v = (std::vector*)rb_num2ulong(addr);
return rb_uint2inum((uint32_t)&v->at(FIX2INT(idx)));
}
-static VALUE rb_dfmemory_vec16_insert(VALUE self, VALUE addr, VALUE idx, VALUE val)
+static VALUE rb_dfmemory_vec16_insertat(VALUE self, VALUE addr, VALUE idx, VALUE val)
{
std::vector *v = (std::vector*)rb_num2ulong(addr);
v->insert(v->begin()+FIX2INT(idx), rb_num2ulong(val));
return Qtrue;
}
-static VALUE rb_dfmemory_vec16_delete(VALUE self, VALUE addr, VALUE idx)
+static VALUE rb_dfmemory_vec16_deleteat(VALUE self, VALUE addr, VALUE idx)
{
std::vector *v = (std::vector*)rb_num2ulong(addr);
v->erase(v->begin()+FIX2INT(idx));
@@ -686,13 +710,13 @@ static VALUE rb_dfmemory_vec32_ptrat(VALUE self, VALUE addr, VALUE idx)
std::vector *v = (std::vector*)rb_num2ulong(addr);
return rb_uint2inum((uint32_t)&v->at(FIX2INT(idx)));
}
-static VALUE rb_dfmemory_vec32_insert(VALUE self, VALUE addr, VALUE idx, VALUE val)
+static VALUE rb_dfmemory_vec32_insertat(VALUE self, VALUE addr, VALUE idx, VALUE val)
{
std::vector *v = (std::vector*)rb_num2ulong(addr);
v->insert(v->begin()+FIX2INT(idx), rb_num2ulong(val));
return Qtrue;
}
-static VALUE rb_dfmemory_vec32_delete(VALUE self, VALUE addr, VALUE idx)
+static VALUE rb_dfmemory_vec32_deleteat(VALUE self, VALUE addr, VALUE idx)
{
std::vector *v = (std::vector*)rb_num2ulong(addr);
v->erase(v->begin()+FIX2INT(idx));
@@ -700,6 +724,24 @@ static VALUE rb_dfmemory_vec32_delete(VALUE self, VALUE addr, VALUE idx)
}
// vector
+static VALUE rb_dfmemory_vecbool_new(VALUE self)
+{
+ std::vector *ptr = new std::vector;
+ return rb_uint2inum((uint32_t)ptr);
+}
+static VALUE rb_dfmemory_vecbool_delete(VALUE self, VALUE addr)
+{
+ std::vector *ptr = (std::vector*)rb_num2ulong(addr);
+ if (ptr)
+ delete ptr;
+ return Qtrue;
+}
+static VALUE rb_dfmemory_vecbool_init(VALUE self, VALUE addr)
+{
+ std::vector *ptr = new std::vector;
+ memcpy((void*)rb_num2ulong(addr), (void*)ptr, sizeof(*ptr));
+ return Qtrue;
+}
static VALUE rb_dfmemory_vecbool_length(VALUE self, VALUE addr)
{
std::vector *v = (std::vector*)rb_num2ulong(addr);
@@ -716,13 +758,13 @@ static VALUE rb_dfmemory_vecbool_setat(VALUE self, VALUE addr, VALUE idx, VALUE
v->at(FIX2INT(idx)) = (BOOL_ISFALSE(val) ? 0 : 1);
return Qtrue;
}
-static VALUE rb_dfmemory_vecbool_insert(VALUE self, VALUE addr, VALUE idx, VALUE val)
+static VALUE rb_dfmemory_vecbool_insertat(VALUE self, VALUE addr, VALUE idx, VALUE val)
{
std::vector *v = (std::vector*)rb_num2ulong(addr);
v->insert(v->begin()+FIX2INT(idx), (BOOL_ISFALSE(val) ? 0 : 1));
return Qtrue;
}
-static VALUE rb_dfmemory_vecbool_delete(VALUE self, VALUE addr, VALUE idx)
+static VALUE rb_dfmemory_vecbool_deleteat(VALUE self, VALUE addr, VALUE idx)
{
std::vector *v = (std::vector*)rb_num2ulong(addr);
v->erase(v->begin()+FIX2INT(idx));
@@ -834,27 +876,34 @@ static void ruby_bind_dfhack(void) {
rb_define_singleton_method(rb_cDFHack, "memory_write_int32", RUBY_METHOD_FUNC(rb_dfmemory_write_int32), 2);
rb_define_singleton_method(rb_cDFHack, "memory_write_float", RUBY_METHOD_FUNC(rb_dfmemory_write_float), 2);
+ rb_define_singleton_method(rb_cDFHack, "memory_stlstring_new", RUBY_METHOD_FUNC(rb_dfmemory_stlstring_new), 0);
+ rb_define_singleton_method(rb_cDFHack, "memory_stlstring_delete", RUBY_METHOD_FUNC(rb_dfmemory_stlstring_delete), 1);
rb_define_singleton_method(rb_cDFHack, "memory_stlstring_init", RUBY_METHOD_FUNC(rb_dfmemory_stlstring_init), 1);
rb_define_singleton_method(rb_cDFHack, "memory_read_stlstring", RUBY_METHOD_FUNC(rb_dfmemory_read_stlstring), 1);
rb_define_singleton_method(rb_cDFHack, "memory_write_stlstring", RUBY_METHOD_FUNC(rb_dfmemory_write_stlstring), 2);
+ rb_define_singleton_method(rb_cDFHack, "memory_vector_new", RUBY_METHOD_FUNC(rb_dfmemory_vec_new), 0);
+ rb_define_singleton_method(rb_cDFHack, "memory_vector_delete", RUBY_METHOD_FUNC(rb_dfmemory_vec_delete), 1);
rb_define_singleton_method(rb_cDFHack, "memory_vector_init", RUBY_METHOD_FUNC(rb_dfmemory_vec_init), 1);
rb_define_singleton_method(rb_cDFHack, "memory_vector8_length", RUBY_METHOD_FUNC(rb_dfmemory_vec8_length), 1);
rb_define_singleton_method(rb_cDFHack, "memory_vector8_ptrat", RUBY_METHOD_FUNC(rb_dfmemory_vec8_ptrat), 2);
- rb_define_singleton_method(rb_cDFHack, "memory_vector8_insert", RUBY_METHOD_FUNC(rb_dfmemory_vec8_insert), 3);
- rb_define_singleton_method(rb_cDFHack, "memory_vector8_delete", RUBY_METHOD_FUNC(rb_dfmemory_vec8_delete), 2);
+ rb_define_singleton_method(rb_cDFHack, "memory_vector8_insertat", RUBY_METHOD_FUNC(rb_dfmemory_vec8_insertat), 3);
+ rb_define_singleton_method(rb_cDFHack, "memory_vector8_deleteat", RUBY_METHOD_FUNC(rb_dfmemory_vec8_deleteat), 2);
rb_define_singleton_method(rb_cDFHack, "memory_vector16_length", RUBY_METHOD_FUNC(rb_dfmemory_vec16_length), 1);
rb_define_singleton_method(rb_cDFHack, "memory_vector16_ptrat", RUBY_METHOD_FUNC(rb_dfmemory_vec16_ptrat), 2);
- rb_define_singleton_method(rb_cDFHack, "memory_vector16_insert", RUBY_METHOD_FUNC(rb_dfmemory_vec16_insert), 3);
- rb_define_singleton_method(rb_cDFHack, "memory_vector16_delete", RUBY_METHOD_FUNC(rb_dfmemory_vec16_delete), 2);
+ rb_define_singleton_method(rb_cDFHack, "memory_vector16_insertat", RUBY_METHOD_FUNC(rb_dfmemory_vec16_insertat), 3);
+ rb_define_singleton_method(rb_cDFHack, "memory_vector16_deleteat", RUBY_METHOD_FUNC(rb_dfmemory_vec16_deleteat), 2);
rb_define_singleton_method(rb_cDFHack, "memory_vector32_length", RUBY_METHOD_FUNC(rb_dfmemory_vec32_length), 1);
rb_define_singleton_method(rb_cDFHack, "memory_vector32_ptrat", RUBY_METHOD_FUNC(rb_dfmemory_vec32_ptrat), 2);
- rb_define_singleton_method(rb_cDFHack, "memory_vector32_insert", RUBY_METHOD_FUNC(rb_dfmemory_vec32_insert), 3);
- rb_define_singleton_method(rb_cDFHack, "memory_vector32_delete", RUBY_METHOD_FUNC(rb_dfmemory_vec32_delete), 2);
+ rb_define_singleton_method(rb_cDFHack, "memory_vector32_insertat", RUBY_METHOD_FUNC(rb_dfmemory_vec32_insertat), 3);
+ rb_define_singleton_method(rb_cDFHack, "memory_vector32_deleteat", RUBY_METHOD_FUNC(rb_dfmemory_vec32_deleteat), 2);
+ rb_define_singleton_method(rb_cDFHack, "memory_vectorbool_new", RUBY_METHOD_FUNC(rb_dfmemory_vecbool_new), 0);
+ rb_define_singleton_method(rb_cDFHack, "memory_vectorbool_delete", RUBY_METHOD_FUNC(rb_dfmemory_vecbool_delete), 1);
+ rb_define_singleton_method(rb_cDFHack, "memory_vectorbool_init", RUBY_METHOD_FUNC(rb_dfmemory_vecbool_init), 1);
rb_define_singleton_method(rb_cDFHack, "memory_vectorbool_length", RUBY_METHOD_FUNC(rb_dfmemory_vecbool_length), 1);
rb_define_singleton_method(rb_cDFHack, "memory_vectorbool_at", RUBY_METHOD_FUNC(rb_dfmemory_vecbool_at), 2);
rb_define_singleton_method(rb_cDFHack, "memory_vectorbool_setat", RUBY_METHOD_FUNC(rb_dfmemory_vecbool_setat), 3);
- rb_define_singleton_method(rb_cDFHack, "memory_vectorbool_insert", RUBY_METHOD_FUNC(rb_dfmemory_vecbool_insert), 3);
- rb_define_singleton_method(rb_cDFHack, "memory_vectorbool_delete", RUBY_METHOD_FUNC(rb_dfmemory_vecbool_delete), 2);
+ rb_define_singleton_method(rb_cDFHack, "memory_vectorbool_insertat", RUBY_METHOD_FUNC(rb_dfmemory_vecbool_insertat), 3);
+ rb_define_singleton_method(rb_cDFHack, "memory_vectorbool_deleteat", RUBY_METHOD_FUNC(rb_dfmemory_vecbool_deleteat), 2);
rb_define_singleton_method(rb_cDFHack, "memory_bitarray_length", RUBY_METHOD_FUNC(rb_dfmemory_bitarray_length), 1);
rb_define_singleton_method(rb_cDFHack, "memory_bitarray_resize", RUBY_METHOD_FUNC(rb_dfmemory_bitarray_resize), 2);
rb_define_singleton_method(rb_cDFHack, "memory_bitarray_isset", RUBY_METHOD_FUNC(rb_dfmemory_bitarray_isset), 2);
From 8f4c39d3f5ef22ce4065741e1d0cccde20497493 Mon Sep 17 00:00:00 2001
From: jj
Date: Thu, 9 Aug 2012 17:07:20 +0200
Subject: [PATCH 18/92] showmood: fix fetched/needed quantity calculation
---
plugins/showmood.cpp | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/plugins/showmood.cpp b/plugins/showmood.cpp
index 10d7b52c2..0b3fa8a99 100644
--- a/plugins/showmood.cpp
+++ b/plugins/showmood.cpp
@@ -12,6 +12,7 @@
#include "df/world.h"
#include "df/job.h"
#include "df/job_item.h"
+#include "df/job_item_ref.h"
#include "df/general_ref.h"
#include "df/builtin_mats.h"
#include "df/inorganic_raw.h"
@@ -165,7 +166,10 @@ command_result df_showmood (color_ostream &out, vector & parameters)
out.print("not yet claimed a workshop but will want");
out.print(" the following items:\n");
- int count_got = job->items.size(), got;
+ // total amount of stuff fetched so far
+ int count_got = 0;
+ for (size_t i = 0; i < job->items.size(); i++)
+ count_got += job->items[i]->item->getTotalDimension();
for (size_t i = 0; i < job->job_items.size(); i++)
{
@@ -269,7 +273,9 @@ command_result df_showmood (color_ostream &out, vector & parameters)
}
}
- got = count_got;
+ // total amount of stuff fetched for this requirement
+ // XXX may fail with cloth/thread/bars if need 1 and fetch 2
+ int got = count_got;
if (got > item->quantity)
got = item->quantity;
out.print(", quantity %i (got %i)\n", item->quantity, got);
From 942b245461606a902b6cfda38fcdbf9e3b6c3131 Mon Sep 17 00:00:00 2001
From: jj
Date: Sat, 11 Aug 2012 20:08:33 +0200
Subject: [PATCH 19/92] ruby: add method to check if an item is free for use as
construction material
---
plugins/ruby/building.rb | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/plugins/ruby/building.rb b/plugins/ruby/building.rb
index 9a59411f9..ab029ac24 100644
--- a/plugins/ruby/building.rb
+++ b/plugins/ruby/building.rb
@@ -286,14 +286,23 @@ module DFHack
job
end
+ # check item flags to see if it is suitable for use as a building material
+ def building_isitemfree(i)
+ !i.flags.in_job and
+ !i.flags.in_inventory and
+ !i.flags.removed and
+ !i.flags.in_building and
+ !i.flags.owned and
+ !i.flags.forbid
+ end
+
# exemple usage
def buildbed(pos=cursor)
raise 'where to ?' if pos.x < 0
item = world.items.all.find { |i|
i.kind_of?(ItemBedst) and
- i.itemrefs.empty? and
- !i.flags.in_job
+ building_isitemfree(i)
}
raise 'no free bed, build more !' if not item
From 4c720c75046ccdefb7705a1d3742f22d75a314fe Mon Sep 17 00:00:00 2001
From: jj
Date: Sat, 11 Aug 2012 20:11:00 +0200
Subject: [PATCH 20/92] ruby: add explicit paths everywhere for ruby-autogen
---
plugins/ruby/CMakeLists.txt | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/plugins/ruby/CMakeLists.txt b/plugins/ruby/CMakeLists.txt
index 0d9f1187d..e10ee38bf 100644
--- a/plugins/ruby/CMakeLists.txt
+++ b/plugins/ruby/CMakeLists.txt
@@ -18,12 +18,12 @@ IF (DL_RUBY AND NOT APPLE)
ENDIF(DL_RUBY AND NOT APPLE)
ADD_CUSTOM_COMMAND(
- OUTPUT ruby-autogen.rb
- COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/codegen.pl ${dfhack_SOURCE_DIR}/library/include/df/codegen.out.xml ruby-autogen.rb
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/ruby-autogen.rb
+ COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/codegen.pl ${dfhack_SOURCE_DIR}/library/include/df/codegen.out.xml ${CMAKE_CURRENT_BINARY_DIR}/ruby-autogen.rb
DEPENDS ${dfhack_SOURCE_DIR}/library/include/df/codegen.out.xml ${CMAKE_CURRENT_SOURCE_DIR}/codegen.pl
COMMENT ruby-autogen.rb
)
-ADD_CUSTOM_TARGET(ruby-autogen-rb DEPENDS ruby-autogen.rb)
+ADD_CUSTOM_TARGET(ruby-autogen-rb DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/ruby-autogen.rb)
INCLUDE_DIRECTORIES("${dfhack_SOURCE_DIR}/depends/tthread")
From cb04a082fd60499c4463809787b1f9b93b7b0f1b Mon Sep 17 00:00:00 2001
From: jj
Date: Sat, 11 Aug 2012 21:41:47 +0200
Subject: [PATCH 21/92] move script/fixstuckdoors to script/fix/stuckdoors
---
scripts/{fixstuckdoors.rb => fix/stuckdoors.rb} | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename scripts/{fixstuckdoors.rb => fix/stuckdoors.rb} (100%)
diff --git a/scripts/fixstuckdoors.rb b/scripts/fix/stuckdoors.rb
similarity index 100%
rename from scripts/fixstuckdoors.rb
rename to scripts/fix/stuckdoors.rb
From 2362bb8eea2d45352fc42c995d8aa2d0fb2b4689 Mon Sep 17 00:00:00 2001
From: jj
Date: Sat, 11 Aug 2012 22:25:08 +0200
Subject: [PATCH 22/92] ruby: add popup_announcement method
---
plugins/ruby/ui.rb | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/plugins/ruby/ui.rb b/plugins/ruby/ui.rb
index 6d2b5c2cd..9dded66c2 100644
--- a/plugins/ruby/ui.rb
+++ b/plugins/ruby/ui.rb
@@ -68,5 +68,14 @@ module DFHack
world.status.display_timer = 2000
end
end
+
+ # add an announcement to display in a game popup message
+ # (eg "the megabeast foobar arrived")
+ def popup_announcement(str, color=nil, bright=nil)
+ pop = PopupMessage.cpp_new(:text => str)
+ pop.color = color if color
+ pop.bright = bright if bright
+ world.status.popups << pop
+ end
end
end
From 85f1a6fa6ac2248f3d4b867c70e220fbed55c651 Mon Sep 17 00:00:00 2001
From: jj
Date: Sat, 11 Aug 2012 22:25:40 +0200
Subject: [PATCH 23/92] add fix/loyaltycascade script
---
scripts/fix/loyaltycascade.rb | 51 +++++++++++++++++++++++++++++++++++
1 file changed, 51 insertions(+)
create mode 100644 scripts/fix/loyaltycascade.rb
diff --git a/scripts/fix/loyaltycascade.rb b/scripts/fix/loyaltycascade.rb
new file mode 100644
index 000000000..632f8024e
--- /dev/null
+++ b/scripts/fix/loyaltycascade.rb
@@ -0,0 +1,51 @@
+# script to fix loyalty cascade, when you order your militia to kill friendly units
+
+def fixunit(u)
+ return if u.race != df.ui.race_id or u.civ_id != df.ui.civ_id
+ links = u.hist_figure_tg.entity_links
+ fixed = false
+
+ if i1 = links.index { |l|
+ l.kind_of?(DFHack::HistfigEntityLinkFormerMemberst) and
+ l.entity_id == df.ui.civ_id
+ } and i2 = links.index { |l|
+ l.kind_of?(DFHack::HistfigEntityLinkEnemyst) and
+ l.entity_id == df.ui.civ_id
+ }
+ fixed = true
+ i1, i2 = i2, i1 if i1 > i2
+ links.delete_at i2
+ links.delete_at i1
+ links << DFHack::HistfigEntityLinkMemberst.cpp_new(:entity_id => df.ui.civ_id, :link_strength => 100)
+ df.add_announcement "fixloyalty: #{u.name} is now a member of #{df.ui.civ_tg.name} again"
+ end
+
+ if i1 = links.index { |l|
+ l.kind_of?(DFHack::HistfigEntityLinkFormerMemberst) and
+ l.entity_id == df.ui.group_id
+ } and i2 = links.index { |l|
+ l.kind_of?(DFHack::HistfigEntityLinkEnemyst) and
+ l.entity_id == df.ui.group_id
+ }
+ fixed = true
+ i1, i2 = i2, i1 if i1 > i2
+ links.delete_at i2
+ links.delete_at i1
+ links << DFHack::HistfigEntityLinkMemberst.cpp_new(:entity_id => df.ui.group_id, :link_strength => 100)
+ df.add_announcement "fixloyalty: #{u.name} is now a member of #{df.ui.group_tg.name} again"
+ end
+
+ fixed
+end
+
+fixed = 0
+df.unit_citizens.each { |u|
+ fixed += 1 if fixunit(u)
+}
+
+if fixed > 0
+ df.popup_announcement "Fixed a loyalty cascade, you should save and reload now"
+ puts "loyalty cascade fixed (#{fixed} dwarves), you should save and reload"
+else
+ puts "no loyalty cascade found"
+end
From 030bd8ab571a631f955a3ae19813f6adb078e818 Mon Sep 17 00:00:00 2001
From: jj
Date: Sun, 12 Aug 2012 00:24:34 +0200
Subject: [PATCH 24/92] fix/loyaltycascade: clear the enemy status cache, dont
require a save/reload anymore
---
plugins/ruby/ruby-autogen-defs.rb | 1 +
scripts/fix/loyaltycascade.rb | 31 +++++++++++++++++++++----------
2 files changed, 22 insertions(+), 10 deletions(-)
diff --git a/plugins/ruby/ruby-autogen-defs.rb b/plugins/ruby/ruby-autogen-defs.rb
index 7165e2448..3507508e1 100644
--- a/plugins/ruby/ruby-autogen-defs.rb
+++ b/plugins/ruby/ruby-autogen-defs.rb
@@ -361,6 +361,7 @@ module DFHack
def empty? ; length == 0 ; end
def flatten ; map { |e| e.respond_to?(:flatten) ? e.flatten : e }.flatten ; end
def index(e=nil, &b) ; (0...length).find { |i| b ? b[self[i]] : self[i] == e } ; end
+ def map! ; (0...length).each { |i| self[i] = yield(self[i]) } ; end
def first ; self[0] ; end
def last ; self[length-1] ; end
end
diff --git a/scripts/fix/loyaltycascade.rb b/scripts/fix/loyaltycascade.rb
index 632f8024e..2f987bd55 100644
--- a/scripts/fix/loyaltycascade.rb
+++ b/scripts/fix/loyaltycascade.rb
@@ -1,10 +1,11 @@
# script to fix loyalty cascade, when you order your militia to kill friendly units
-def fixunit(u)
- return if u.race != df.ui.race_id or u.civ_id != df.ui.civ_id
- links = u.hist_figure_tg.entity_links
+def fixunit(unit)
+ return if unit.race != df.ui.race_id or unit.civ_id != df.ui.civ_id
+ links = unit.hist_figure_tg.entity_links
fixed = false
+ # check if the unit is a civ renegade
if i1 = links.index { |l|
l.kind_of?(DFHack::HistfigEntityLinkFormerMemberst) and
l.entity_id == df.ui.civ_id
@@ -17,9 +18,10 @@ def fixunit(u)
links.delete_at i2
links.delete_at i1
links << DFHack::HistfigEntityLinkMemberst.cpp_new(:entity_id => df.ui.civ_id, :link_strength => 100)
- df.add_announcement "fixloyalty: #{u.name} is now a member of #{df.ui.civ_tg.name} again"
+ df.add_announcement "fixloyalty: #{unit.name} is now a member of #{df.ui.civ_tg.name} again"
end
+ # check if the unit is a group renegade
if i1 = links.index { |l|
l.kind_of?(DFHack::HistfigEntityLinkFormerMemberst) and
l.entity_id == df.ui.group_id
@@ -32,20 +34,29 @@ def fixunit(u)
links.delete_at i2
links.delete_at i1
links << DFHack::HistfigEntityLinkMemberst.cpp_new(:entity_id => df.ui.group_id, :link_strength => 100)
- df.add_announcement "fixloyalty: #{u.name} is now a member of #{df.ui.group_tg.name} again"
+ df.add_announcement "fixloyalty: #{unit.name} is now a member of #{df.ui.group_tg.name} again"
end
+ # fix the 'is an enemy' cache matrix (mark to be recalculated by the game when needed)
+ if fixed and unit.unknown8.enemy_status_slot != -1
+ i = unit.unknown8.enemy_status_slot
+ unit.unknown8.enemy_status_slot = -1
+ df.world.enemy_status_cache.slot_used[i] = false
+ df.world.enemy_status_cache.rel_map[i].map! { -1 }
+ df.world.enemy_status_cache.rel_map.each { |a| a[i] = -1 }
+ end
+
+ # return true if we actually fixed the unit
fixed
end
-fixed = 0
+count = 0
df.unit_citizens.each { |u|
- fixed += 1 if fixunit(u)
+ count += 1 if fixunit(u)
}
-if fixed > 0
- df.popup_announcement "Fixed a loyalty cascade, you should save and reload now"
- puts "loyalty cascade fixed (#{fixed} dwarves), you should save and reload"
+if count > 0
+ puts "loyalty cascade fixed (#{count} dwarves)"
else
puts "no loyalty cascade found"
end
From 61185d29cae36bf8bd33287acd019ec0db50ce50 Mon Sep 17 00:00:00 2001
From: jj
Date: Sun, 12 Aug 2012 00:27:20 +0200
Subject: [PATCH 25/92] console-linux: silence minor gcc warnings
---
library/Console-linux.cpp | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/library/Console-linux.cpp b/library/Console-linux.cpp
index 6b4de736d..882d9527d 100644
--- a/library/Console-linux.cpp
+++ b/library/Console-linux.cpp
@@ -62,7 +62,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// George Vulov for MacOSX
#ifndef __LINUX__
-#define TEMP_FAILURE_RETRY(expr) \
+#define TMP_FAILURE_RETRY(expr) \
({ long int _res; \
do _res = (long int) (expr); \
while (_res == -1L && errno == EINTR); \
@@ -155,7 +155,7 @@ namespace DFHack
FD_ZERO(&descriptor_set);
FD_SET(STDIN_FILENO, &descriptor_set);
FD_SET(exit_pipe[0], &descriptor_set);
- int ret = TEMP_FAILURE_RETRY(
+ int ret = TMP_FAILURE_RETRY(
select (FD_SETSIZE,&descriptor_set, NULL, NULL, NULL)
);
if(ret == -1)
@@ -165,7 +165,7 @@ namespace DFHack
if (FD_ISSET(STDIN_FILENO, &descriptor_set))
{
// read byte from stdin
- ret = TEMP_FAILURE_RETRY(
+ ret = TMP_FAILURE_RETRY(
read(STDIN_FILENO, &out, 1)
);
if(ret == -1)
@@ -245,7 +245,8 @@ namespace DFHack
if(rawmode)
{
const char * clr = "\033c\033[3J\033[H";
- ::write(STDIN_FILENO,clr,strlen(clr));
+ if (::write(STDIN_FILENO,clr,strlen(clr)) == -1)
+ ;
}
else
{
@@ -269,7 +270,8 @@ namespace DFHack
{
const char * colstr = getANSIColor(index);
int lstr = strlen(colstr);
- ::write(STDIN_FILENO,colstr,lstr);
+ if (::write(STDIN_FILENO,colstr,lstr) == -1)
+ ;
}
}
/// Reset color to default
@@ -656,7 +658,8 @@ bool Console::init(bool sharing)
inited = false;
return false;
}
- freopen("stdout.log", "w", stdout);
+ if (!freopen("stdout.log", "w", stdout))
+ ;
d = new Private();
// make our own weird streams so our IO isn't redirected
d->dfout_C = fopen("/dev/tty", "w");
@@ -664,7 +667,8 @@ bool Console::init(bool sharing)
clear();
d->supported_terminal = !isUnsupportedTerm() && isatty(STDIN_FILENO);
// init the exit mechanism
- pipe(d->exit_pipe);
+ if (pipe(d->exit_pipe) == -1)
+ ;
FD_ZERO(&d->descriptor_set);
FD_SET(STDIN_FILENO, &d->descriptor_set);
FD_SET(d->exit_pipe[0], &d->descriptor_set);
From eb524105653bd09a33eae2da6f21d1d1d5e6a530 Mon Sep 17 00:00:00 2001
From: jj
Date: Sun, 12 Aug 2012 00:46:03 +0200
Subject: [PATCH 26/92] fix/loyaltycascade: reset enemy_status_cache.next_slot
too
---
scripts/fix/loyaltycascade.rb | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/scripts/fix/loyaltycascade.rb b/scripts/fix/loyaltycascade.rb
index 2f987bd55..6fad2947f 100644
--- a/scripts/fix/loyaltycascade.rb
+++ b/scripts/fix/loyaltycascade.rb
@@ -41,9 +41,11 @@ def fixunit(unit)
if fixed and unit.unknown8.enemy_status_slot != -1
i = unit.unknown8.enemy_status_slot
unit.unknown8.enemy_status_slot = -1
- df.world.enemy_status_cache.slot_used[i] = false
- df.world.enemy_status_cache.rel_map[i].map! { -1 }
- df.world.enemy_status_cache.rel_map.each { |a| a[i] = -1 }
+ cache = df.world.enemy_status_cache
+ cache.slot_used[i] = false
+ cache.rel_map[i].map! { -1 }
+ cache.rel_map.each { |a| a[i] = -1 }
+ cache.next_slot = i if cache.next_slot > i
end
# return true if we actually fixed the unit
From 5a880d619c6e51093ff06bf7d8b99e672740bc76 Mon Sep 17 00:00:00 2001
From: "jj@jj"
Date: Sun, 12 Aug 2012 22:13:01 +0200
Subject: [PATCH 27/92] ruby: add MapTile#dig, tweak unit_iscitizen
---
plugins/ruby/README | 3 +--
plugins/ruby/map.rb | 5 ++++
plugins/ruby/unit.rb | 60 ++++++++++++++++++++++++++------------------
3 files changed, 42 insertions(+), 26 deletions(-)
diff --git a/plugins/ruby/README b/plugins/ruby/README
index 8a473f332..c9a84fb37 100644
--- a/plugins/ruby/README
+++ b/plugins/ruby/README
@@ -213,8 +213,7 @@ Find the raws name of the plant under cursor
p df.world.raws.plants.all[plant.mat_index].id
Dig a channel under the cursor
- df.map_designation_at(df.cursor).dig = :Channel
- df.map_block_at(df.cursor).flags.designated = true
+ df.map_tile_at(df.cursor).dig(:Channel)
Spawn 2/7 magma on the tile of the dwarf nicknamed 'hotfeet'
hot = df.unit_citizens.find { |u| u.name.nickname == 'hotfeet' }
diff --git a/plugins/ruby/map.rb b/plugins/ruby/map.rb
index c99d5b88d..dccea7291 100644
--- a/plugins/ruby/map.rb
+++ b/plugins/ruby/map.rb
@@ -188,6 +188,11 @@ module DFHack
"#"
end
+ def dig(mode=:Default)
+ designation.dig = mode
+ mapblock.flags.designated = true
+ end
+
def spawn_liquid(quantity, is_magma=false, flowing=true)
designation.flow_size = quantity
designation.liquid_type = (is_magma ? :Magma : :Water)
diff --git a/plugins/ruby/unit.rb b/plugins/ruby/unit.rb
index ebcf249da..1a619c5ce 100644
--- a/plugins/ruby/unit.rb
+++ b/plugins/ruby/unit.rb
@@ -41,48 +41,60 @@ module DFHack
# returns an Array of all units that are current fort citizen (dwarves, on map, not hostile)
def unit_citizens
- race = ui.race_id
- civ = ui.civ_id
world.units.active.find_all { |u|
- u.race == race and u.civ_id == civ and !u.flags1.dead and !u.flags1.merchant and
- !u.flags1.diplomat and !u.flags2.resident and !u.flags3.ghostly and
- !u.curse.add_tags1.OPPOSED_TO_LIFE and !u.curse.add_tags1.CRAZED and
- u.mood != :Berserk
- # TODO check curse ; currently this should keep vampires, but may include werebeasts
+ unit_iscitizen(u)
}
end
+ def unit_iscitizen(u)
+ u.race == ui.race_id and u.civ_id == ui.civ_id and !u.flags1.dead and !u.flags1.merchant and
+ !u.flags1.diplomat and !u.flags2.resident and !u.flags3.ghostly and
+ !u.curse.add_tags1.OPPOSED_TO_LIFE and !u.curse.add_tags1.CRAZED and
+ u.mood != :Berserk
+ # TODO check curse ; currently this should keep vampires, but may include werebeasts
+ end
+
# list workers (citizen, not crazy / child / inmood / noble)
def unit_workers
- unit_citizens.find_all { |u|
- u.mood == :None and
- u.profession != :CHILD and
- u.profession != :BABY and
- # TODO MENIAL_WORK_EXEMPTION_SPOUSE
- !unit_entitypositions(u).find { |pos| pos.flags[:MENIAL_WORK_EXEMPTION] }
+ world.units.active.find_all { |u|
+ unit_isworker(u)
}
end
+ def unit_isworker(u)
+ unit_iscitizen(u) and
+ u.mood == :None and
+ u.profession != :CHILD and
+ u.profession != :BABY and
+ # TODO MENIAL_WORK_EXEMPTION_SPOUSE
+ !unit_entitypositions(u).find { |pos| pos.flags[:MENIAL_WORK_EXEMPTION] }
+ end
+
# list currently idle workers
def unit_idlers
- unit_workers.find_all { |u|
- # current_job includes eat/drink/sleep/pickupequip
- !u.job.current_job and
- # filter 'attend meeting'
- not u.specific_refs.find { |s| s.type == :ACTIVITY } and
- # filter soldiers (TODO check schedule)
- u.military.squad_index == -1 and
- # filter 'on break'
- not u.status.misc_traits.find { |t| t.id == :OnBreak }
+ world.units.active.find_all { |u|
+ unit_isidler(u)
}
end
+ def unit_isidler(u)
+ unit_isworker(u) and
+ # current_job includes eat/drink/sleep/pickupequip
+ !u.job.current_job and
+ # filter 'attend meeting'
+ not u.specific_refs.find { |s| s.type == :ACTIVITY } and
+ # filter soldiers (TODO check schedule)
+ u.military.squad_index == -1 and
+ # filter 'on break'
+ not u.status.misc_traits.find { |t| t.id == :OnBreak }
+ end
+
def unit_entitypositions(unit)
list = []
- return list if not hf = world.history.figures.binsearch(unit.hist_figure_id)
+ return list if not hf = unit.hist_figure_tg
hf.entity_links.each { |el|
next if el._rtti_classname != :histfig_entity_link_positionst
- next if not ent = world.entities.all.binsearch(el.entity_id)
+ next if not ent = el.entity_tg
next if not pa = ent.positions.assignments.binsearch(el.assignment_id)
next if not pos = ent.positions.own.binsearch(pa.position_id)
list << pos
From 53a05365066ba47da2e047e4b8ef87d2a80405d4 Mon Sep 17 00:00:00 2001
From: jj
Date: Mon, 13 Aug 2012 00:46:27 +0200
Subject: [PATCH 28/92] ruby: typo in building_deconstruct
---
plugins/ruby/building.rb | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/plugins/ruby/building.rb b/plugins/ruby/building.rb
index ab029ac24..af152e198 100644
--- a/plugins/ruby/building.rb
+++ b/plugins/ruby/building.rb
@@ -279,9 +279,9 @@ module DFHack
job = Job.cpp_new
refbuildingholder = GeneralRefBuildingHolderst.cpp_new
job.job_type = :DestroyBuilding
- refbuildingholder.building_id = building.id
+ refbuildingholder.building_id = bld.id
job.references << refbuildingholder
- building.jobs << job
+ bld.jobs << job
job_link job
job
end
From e659d845ab63c1e354deafe351b9a86d5861168f Mon Sep 17 00:00:00 2001
From: jj
Date: Mon, 13 Aug 2012 02:06:56 +0200
Subject: [PATCH 29/92] ruby: fix LinkList.next=
---
plugins/ruby/ruby-autogen-defs.rb | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/plugins/ruby/ruby-autogen-defs.rb b/plugins/ruby/ruby-autogen-defs.rb
index 3507508e1..0cee6426f 100644
--- a/plugins/ruby/ruby-autogen-defs.rb
+++ b/plugins/ruby/ruby-autogen-defs.rb
@@ -666,9 +666,9 @@ module DFHack
@_tg = tg
end
- field(:_ptr, 0) { number 32, false }
- field(:_prev, 4) { number 32, false }
- field(:_next, 8) { number 32, false }
+ field(:_ptr, 0) { pointer }
+ field(:_prev, 4) { pointer }
+ field(:_next, 8) { pointer }
def item
# With the current xml structure, currently _tg designate
@@ -682,22 +682,24 @@ module DFHack
def item=(v)
#addr = _ptr
- #raise 'null pointer' if addr == 0
+ #raise 'null pointer' if not addr
#@_tg.at(addr)._set(v)
raise 'null pointer'
end
def prev
addr = _prev
- return if addr == 0
+ return if not addr
@_tg._at(addr)._get
end
def next
addr = _next
- return if addr == 0
+ return if not addr
@_tg._at(addr)._get
end
+ alias next= _next=
+ alias prev= _prev=
include Enumerable
def each
From 4eedd6f5f0f79347a45c191eceb73d44a0c16ac9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20Mr=C3=A1zek?=
Date: Mon, 13 Aug 2012 07:39:11 +0200
Subject: [PATCH 30/92] Fix workflow.
---
plugins/workflow.cpp | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/plugins/workflow.cpp b/plugins/workflow.cpp
index 0b87b3590..a077db05a 100644
--- a/plugins/workflow.cpp
+++ b/plugins/workflow.cpp
@@ -285,7 +285,7 @@ struct ItemConstraint {
int weight;
std::vector jobs;
- enum item_quality min_quality;
+ item_quality::item_quality min_quality;
int item_amount, item_count, item_inuse;
bool request_suspend, request_resume;
@@ -296,8 +296,7 @@ struct ItemConstraint {
public:
ItemConstraint()
- : is_craft(false), weight(0), item_amount(0), item_count(0), item_inuse(0)
- , is_active(false), cant_resume_reported(false), min_quality(Ordinary)
+ : is_craft(false), weight(0), min_quality(Ordinary),item_amount(0), item_count(0), item_inuse(0), is_active(false), cant_resume_reported(false)
{}
int goalCount() { return config.ival(0); }
@@ -685,7 +684,7 @@ static ItemConstraint *get_constraint(color_ostream &out, const std::string &str
return NULL;
}
- enum item_quality minqual = Ordinary;
+ item_quality::item_quality minqual = Ordinary;
std::string qualstr = vector_get(tokens, 3);
if(!qualstr.empty()) {
if(qualstr == "ordinary") minqual = Ordinary;
@@ -1504,13 +1503,14 @@ static command_result workflow_cmd(color_ostream &out, vector & paramet
}
df::building *workshop = NULL;
- df::job *job = NULL;
+ //FIXME: unused variable!
+ //df::job *job = NULL;
if (Gui::dwarfmode_hotkey(Core::getTopViewscreen()) &&
ui->main.mode == ui_sidebar_mode::QueryBuilding)
{
workshop = world->selected_building;
- job = Gui::getSelectedWorkshopJob(out, true);
+ //job = Gui::getSelectedWorkshopJob(out, true);
}
std::string cmd = parameters.empty() ? "list" : parameters[0];
From cde97bba6f5fe09c3a46babd073e8e1d30be3cdf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20Mr=C3=A1zek?=
Date: Mon, 13 Aug 2012 07:42:02 +0200
Subject: [PATCH 31/92] Fix workflow some more
---
plugins/workflow.cpp | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/plugins/workflow.cpp b/plugins/workflow.cpp
index a077db05a..162051242 100644
--- a/plugins/workflow.cpp
+++ b/plugins/workflow.cpp
@@ -43,7 +43,6 @@ using std::string;
using std::endl;
using namespace DFHack;
using namespace df::enums;
-using namespace df::enums::item_quality;
using df::global::world;
using df::global::ui;
@@ -296,7 +295,8 @@ struct ItemConstraint {
public:
ItemConstraint()
- : is_craft(false), weight(0), min_quality(Ordinary),item_amount(0), item_count(0), item_inuse(0), is_active(false), cant_resume_reported(false)
+ : is_craft(false), weight(0), min_quality(item_quality::Ordinary),item_amount(0),
+ item_count(0), item_inuse(0), is_active(false), cant_resume_reported(false)
{}
int goalCount() { return config.ival(0); }
@@ -684,15 +684,15 @@ static ItemConstraint *get_constraint(color_ostream &out, const std::string &str
return NULL;
}
- item_quality::item_quality minqual = Ordinary;
+ item_quality::item_quality minqual = item_quality::Ordinary;
std::string qualstr = vector_get(tokens, 3);
if(!qualstr.empty()) {
- if(qualstr == "ordinary") minqual = Ordinary;
- else if(qualstr == "wellcrafted") minqual = WellCrafted;
- else if(qualstr == "finelycrafted") minqual = FinelyCrafted;
- else if(qualstr == "superior") minqual = Superior;
- else if(qualstr == "exceptional") minqual = Exceptional;
- else if(qualstr == "masterful") minqual = Masterful;
+ if(qualstr == "ordinary") minqual = item_quality::Ordinary;
+ else if(qualstr == "wellcrafted") minqual = item_quality::WellCrafted;
+ else if(qualstr == "finelycrafted") minqual = item_quality::FinelyCrafted;
+ else if(qualstr == "superior") minqual = item_quality::Superior;
+ else if(qualstr == "exceptional") minqual = item_quality::Exceptional;
+ else if(qualstr == "masterful") minqual = item_quality::Masterful;
else {
out.printerr("Cannot find quality: %s\nKnown qualities: ordinary, wellcrafted, finelycrafted, superior, exceptional, masterful\n", qualstr.c_str());
return NULL;
From 509d9570908e1befa537d10285942006d148b3a3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20Mr=C3=A1zek?=
Date: Fri, 17 Aug 2012 13:02:31 +0200
Subject: [PATCH 32/92] Make protobuf behave with multiple build folders
involved.
---
depends/protobuf/CMakeLists.txt | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/depends/protobuf/CMakeLists.txt b/depends/protobuf/CMakeLists.txt
index 570c77b18..24c4b275a 100644
--- a/depends/protobuf/CMakeLists.txt
+++ b/depends/protobuf/CMakeLists.txt
@@ -72,13 +72,13 @@ ELSE()
SET(HASH_SET_CLASS hash_set)
ENDIF()
-CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/config.h.in" "${CMAKE_CURRENT_SOURCE_DIR}/config.h")
+CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/config.h.in" "${CMAKE_CURRENT_BINARY_DIR}/config.h")
SET(LIBPROTOBUF_LITE_HDRS
google/protobuf/io/coded_stream.h
google/protobuf/io/coded_stream_inl.h
google/protobuf/stubs/common.h
-config.h
+${CMAKE_CURRENT_BINARY_DIR}/config.h
google/protobuf/extension_set.h
google/protobuf/generated_message_util.h
google/protobuf/stubs/hash.h
@@ -207,6 +207,7 @@ ENDIF()
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
SET(PROTOBUF_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR})
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIRS})
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
# Protobuf shared libraries
From bcc41c081a43a68042c4757a6569cb690098d9b8 Mon Sep 17 00:00:00 2001
From: Alexander Gavrilov
Date: Fri, 17 Aug 2012 14:32:04 +0400
Subject: [PATCH 33/92] Add a utility function for patching read-only memory.
---
LUA_API.rst | 6 +++++
Lua API.html | 5 ++++
library/Core.cpp | 50 +++++++++++++++++++++++++++++++++++++
library/LuaApi.cpp | 12 +++++++++
library/include/MemAccess.h | 3 +++
5 files changed, 76 insertions(+)
diff --git a/LUA_API.rst b/LUA_API.rst
index 2bb2c949e..449f92b46 100644
--- a/LUA_API.rst
+++ b/LUA_API.rst
@@ -1235,6 +1235,12 @@ and are only documented here for completeness:
Returns a sequence of tables describing virtual memory ranges of the process.
+* ``dfhack.internal.patchMemory(dest,src,count)``
+
+ Like memmove below, but works even if dest is read-only memory, e.g. code.
+ If destination overlaps a completely invalid memory region, or another error
+ occurs, returns false.
+
* ``dfhack.internal.memmove(dest,src,count)``
Wraps the standard memmove function. Accepts both numbers and refs as pointers.
diff --git a/Lua API.html b/Lua API.html
index 2c9a6a8df..7dfc7df00 100644
--- a/Lua API.html
+++ b/Lua API.html
@@ -1409,6 +1409,11 @@ global environment, persistent between calls to the script.
dfhack.internal.getMemRanges()
Returns a sequence of tables describing virtual memory ranges of the process.
+dfhack.internal.patchMemory(dest,src,count)
+Like memmove below, but works even if dest is read-only memory, e.g. code.
+If destination overlaps a completely invalid memory region, or another error
+occurs, returns false.
+
dfhack.internal.memmove(dest,src,count)
Wraps the standard memmove function. Accepts both numbers and refs as pointers.
diff --git a/library/Core.cpp b/library/Core.cpp
index 826576b77..f129d9523 100644
--- a/library/Core.cpp
+++ b/library/Core.cpp
@@ -1548,6 +1548,56 @@ void ClassNameCheck::getKnownClassNames(std::vector &names)
names.push_back(*it);
}
+bool Process::patchMemory(void *target, const void* src, size_t count)
+{
+ uint8_t *sptr = (uint8_t*)target;
+ uint8_t *eptr = sptr + count;
+
+ // Find the valid memory ranges
+ std::vector ranges;
+ getMemRanges(ranges);
+
+ unsigned start = 0;
+ while (start < ranges.size() && ranges[start].end <= sptr)
+ start++;
+ if (start >= ranges.size() || ranges[start].start > sptr)
+ return false;
+
+ unsigned end = start+1;
+ while (end < ranges.size() && ranges[end].start < eptr)
+ {
+ if (ranges[end].start != ranges[end-1].end)
+ return false;
+ end++;
+ }
+ if (ranges[end-1].end < eptr)
+ return false;
+
+ // Verify current permissions
+ for (unsigned i = start; i < end; i++)
+ if (!ranges[i].valid || !(ranges[i].read || ranges[i].execute) || ranges[i].shared)
+ return false;
+
+ // Apply writable permissions & update
+ bool ok = true;
+
+ for (unsigned i = start; i < end && ok; i++)
+ {
+ t_memrange perms = ranges[i];
+ perms.write = perms.read = true;
+ if (!setPermisions(perms, perms))
+ ok = false;
+ }
+
+ if (ok)
+ memmove(target, src, count);
+
+ for (unsigned i = start; i < end && ok; i++)
+ setPermisions(ranges[i], ranges[i]);
+
+ return ok;
+}
+
/*******************************************************************************
M O D U L E S
*******************************************************************************/
diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp
index b0a085eca..108dba88f 100644
--- a/library/LuaApi.cpp
+++ b/library/LuaApi.cpp
@@ -1124,6 +1124,17 @@ static int internal_getMemRanges(lua_State *L)
return 1;
}
+static int internal_patchMemory(lua_State *L)
+{
+ void *dest = checkaddr(L, 1);
+ void *src = checkaddr(L, 2);
+ int size = luaL_checkint(L, 3);
+ if (size < 0) luaL_argerror(L, 1, "negative size");
+ bool ok = Core::getInstance().p->patchMemory(dest, src, size);
+ lua_pushboolean(L, ok);
+ return 1;
+}
+
static int internal_memmove(lua_State *L)
{
void *dest = checkaddr(L, 1);
@@ -1214,6 +1225,7 @@ static const luaL_Reg dfhack_internal_funcs[] = {
{ "setAddress", internal_setAddress },
{ "getVTable", internal_getVTable },
{ "getMemRanges", internal_getMemRanges },
+ { "patchMemory", internal_patchMemory },
{ "memmove", internal_memmove },
{ "memcmp", internal_memcmp },
{ "memscan", internal_memscan },
diff --git a/library/include/MemAccess.h b/library/include/MemAccess.h
index c51df3c64..0e5f618e2 100644
--- a/library/include/MemAccess.h
+++ b/library/include/MemAccess.h
@@ -283,6 +283,9 @@ namespace DFHack
/// modify permisions of memory range
bool setPermisions(const t_memrange & range,const t_memrange &trgrange);
+
+ /// write a possibly read-only memory area
+ bool patchMemory(void *target, const void* src, size_t count);
private:
VersionInfo * my_descriptor;
PlatformSpecific *d;
From 236ffd578b66805fa45d65df79e099d00156bfff Mon Sep 17 00:00:00 2001
From: Alexander Gavrilov
Date: Fri, 17 Aug 2012 22:40:53 +0400
Subject: [PATCH 34/92] Add experimental support for interposing vmethods of
known classes.
The hairiest bit is the abuse of compiler-specific pointer-to-member
internals in order to provide more or less transparent API.
---
CMakeLists.txt | 3 +
library/CMakeLists.txt | 2 +
library/DataDefs.cpp | 8 +
library/VTableInterpose.cpp | 238 ++++++++++++++++++++++++++++++
library/include/DataDefs.h | 11 ++
library/include/DataFuncs.h | 15 +-
library/include/VTableInterpose.h | 158 ++++++++++++++++++++
plugins/devel/CMakeLists.txt | 1 +
plugins/devel/vshook.cpp | 61 ++++++++
9 files changed, 491 insertions(+), 6 deletions(-)
create mode 100644 library/VTableInterpose.cpp
create mode 100644 library/include/VTableInterpose.h
create mode 100644 plugins/devel/vshook.cpp
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f77a6c3bb..dfb13cd5d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -111,6 +111,9 @@ IF(UNIX)
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-g -Wall -Wno-unused-variable")
SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -m32 -march=i686 -mtune=generic -std=c++0x")
SET(CMAKE_C_FLAGS "-fvisibility=hidden -m32 -march=i686 -mtune=generic")
+ELSEIF(MSVC)
+ # for msvc, tell it to always use 8-byte pointers to member functions to avoid confusion
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /vmg /vmm")
ENDIF()
# use shared libraries for protobuf
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index bbf22611b..cd3d52c8c 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -27,6 +27,7 @@ include/Core.h
include/ColorText.h
include/DataDefs.h
include/DataIdentity.h
+include/VTableInterpose.h
include/LuaWrapper.h
include/LuaTools.h
include/Error.h
@@ -53,6 +54,7 @@ SET(MAIN_SOURCES
Core.cpp
ColorText.cpp
DataDefs.cpp
+VTableInterpose.cpp
LuaWrapper.cpp
LuaTypes.cpp
LuaTools.cpp
diff --git a/library/DataDefs.cpp b/library/DataDefs.cpp
index 7f0bacc9e..d6604cdb3 100644
--- a/library/DataDefs.cpp
+++ b/library/DataDefs.cpp
@@ -35,6 +35,7 @@ distribution.
// must be last due to MS stupidity
#include "DataDefs.h"
#include "DataIdentity.h"
+#include "VTableInterpose.h"
#include "MiscUtils.h"
@@ -214,6 +215,13 @@ virtual_identity::virtual_identity(size_t size, TAllocateFn alloc,
{
}
+virtual_identity::~virtual_identity()
+{
+ // Remove interpose entries, so that they don't try accessing this object later
+ for (int i = interpose_list.size()-1; i >= 0; i--)
+ interpose_list[i]->remove();
+}
+
/* Vtable name to identity lookup. */
static std::map name_lookup;
diff --git a/library/VTableInterpose.cpp b/library/VTableInterpose.cpp
new file mode 100644
index 000000000..447070624
--- /dev/null
+++ b/library/VTableInterpose.cpp
@@ -0,0 +1,238 @@
+/*
+https://github.com/peterix/dfhack
+Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com)
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+
+#include "Internal.h"
+
+#include
+#include
+#include