@ -4,218 +4,114 @@
 
			
		
	
		
		
			
				
					
					// With thanks to peterix for DFHack and Quietust for information
 // With thanks to peterix for DFHack and Quietust for information
  
			
		
	
		
		
			
				
					
					// http://www.bay12forums.com/smf/index.php?topic=91166.msg2605147#msg2605147
 // http://www.bay12forums.com/smf/index.php?topic=91166.msg2605147#msg2605147
  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					# include  <map> # include  "Debug.h"  
			
				
				
			
		
	
		
		
			
				
					
					# include  <string> # include  "LuaTools.h"  
			
				
				
			
		
	
		
		
			
				
					
					# include  <vector>  
			
		
	
		
		
			
				
					
					# include  "Console.h"  
			
		
	
		
		
			
				
					
					# include  "Core.h"  
			
		
	
		
		
			
				
					
					# include  "Export.h"  
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					# include  "PluginManager.h" # include  "PluginManager.h"  
			
		
	
		
		
			
				
					
					# include  "modules/World.h" # include  "TileTypes.h"  
			
				
				
			
		
	
		
		
			
				
					
					# include  "modules/Materials.h" 
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					# include  "modules/Items.h"  
			
		
	
		
		
			
				
					
					# include  "modules/Kitchen.h" # include  "modules/Kitchen.h"  
			
		
	
		
		
			
				
					
					# include  "VersionInfo.h" # include  "modules/Maps.h"  
			
				
				
			
		
	
		
		
			
				
					
					# include  "df/world.h" # include  "modules/Persistence.h"  
			
				
				
			
		
	
		
		
			
				
					
					# include  "df/plant_raw.h" # include  "modules/Units.h"  
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					# include  "modules/World.h"  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					# include  "df/item_flags.h" # include  "df/item_flags.h"  
			
		
	
		
		
			
				
					
					# include  "df/items_other_id.h" # include  "df/items_other_id.h"  
			
		
	
		
		
			
				
					
					# include  "df/plant_raw.h"  
			
		
	
		
		
			
				
					
					# include  "df/world.h"  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					# include  <unordered_map>  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					using  namespace  std ;  
			
		
	
		
		
			
				
					
					using  namespace  DFHack ; using  namespace  DFHack ;  
			
		
	
		
		
			
				
					
					using  namespace  df : : enums ; using  namespace  df : : enums ;  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					using  std : : map ;  
			
		
	
		
		
			
				
					
					using  std : : string ;  
			
		
	
		
		
			
				
					
					using  std : : unordered_map ;  
			
		
	
		
		
			
				
					
					using  std : : vector ;  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					DFHACK_PLUGIN ( " seedwatch " ) ; DFHACK_PLUGIN ( " seedwatch " ) ;  
			
		
	
		
		
			
				
					
					DFHACK_PLUGIN_IS_ENABLED ( running ) ;  // whether seedwatch is counting the seeds or not
 DFHACK_PLUGIN_IS_ENABLED ( is_enabled) ;   
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					REQUIRE_GLOBAL ( world ) ; REQUIRE_GLOBAL ( world ) ;  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					const  int  buffer  =  20 ;  // seed number buffer - 20 is reasonable
 namespace  DFHack  {  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					    // for configuration-related logging
 
 
			
		
	
		
		
			
				
					
					    DBG_DECLARE ( seedwatch ,  config ,  DebugCategory : : LINFO ) ; 
 
			
		
	
		
		
			
				
					
					    // for logging during the periodic scan
 
 
			
		
	
		
		
			
				
					
					    DBG_DECLARE ( seedwatch ,  cycle ,  DebugCategory : : LINFO ) ; 
 
			
		
	
		
		
			
				
					
					}  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					// abbreviations for the standard plants
 // abbreviations for the standard plants
  
			
		
	
		
		
			
				
					
					map < string ,  string >  abbreviations ; static  unordered_map < string ,  const  char  * >  abbreviations ;  
			
				
				
			
		
	
		
		
			
				
					
					
static  map < string ,  int32_t >  world_plant_ids ;  
			
				
				
			
		
	
		
		
			
				
					
					bool  ignoreSeeds ( df : : item_flags &  f )  // seeds with the following flags should not be counted
 static  const  int  DEFAULT_TARGET  =  30 ;  
			
				
				
			
		
	
		
		
			
				
					
					{ static  const  int  TARGET_BUFFER  =  20 ;  // seed number buffer; 20 is reasonable
  
			
				
				
			
		
	
		
		
			
				
					
					    return 
 
			
		
	
		
		
			
				
					
					        f . bits . dump  | | 
 
			
		
	
		
		
			
				
					
					        f . bits . forbid  | | 
 
			
		
	
		
		
			
				
					
					        f . bits . garbage_collect  | | 
 
			
		
	
		
		
			
				
					
					        f . bits . hidden  | | 
 
			
		
	
		
		
			
				
					
					        f . bits . hostile  | | 
 
			
		
	
		
		
			
				
					
					        f . bits . on_fire  | | 
 
			
		
	
		
		
			
				
					
					        f . bits . rotten  | | 
 
			
		
	
		
		
			
				
					
					        f . bits . trader  | | 
 
			
		
	
		
		
			
				
					
					        f . bits . in_building  | | 
 
			
		
	
		
		
			
				
					
					        f . bits . in_job ; 
 
			
		
	
		
		
			
				
					
					} ;  
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					// searches abbreviations, returns expansion if so, returns original if not
 static  const  string  CONFIG_KEY  =  string ( plugin_name )  +  " /config " ;  
			
				
				
			
		
	
		
		
			
				
					
					string  searchAbbreviations ( string  in ) static  const  string  SEED_CONFIG_KEY_PREFIX  =  string ( plugin_name )  +  " /seed/ " ;  
			
				
				
			
		
	
		
		
			
				
					
					{ static  PersistentDataItem  config ;  
			
				
				
			
		
	
		
		
			
				
					
					    if ( abbreviations . count ( in )  >  0 ) 
static  unordered_map < int ,  PersistentDataItem >  watched_seeds ;  
			
				
				
			
		
	
		
		
			
				
					
					    { 
 
			
				
				
			
		
	
		
		
			
				
					
					        return  abbreviations [ in ] ; 
enum  ConfigValues  {  
			
				
				
			
		
	
		
		
			
				
					
					    } 
    CONFIG_IS_ENABLED  =  0 , 
 
			
				
				
			
		
	
		
		
			
				
					
					    else 
 
			
		
	
		
		
			
				
					
					    { 
 
			
		
	
		
		
			
				
					
					        return  in ; 
 
			
		
	
		
		
			
				
					
					    } 
 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					} ; } ;  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					DFhackCExport  command_result  plugin_enable ( color_ostream  & out ,  bool  enable ) enum  SeedConfigValues  {  
			
				
				
			
		
	
		
		
			
				
					
					{     SEED_CONFIG_ID  =  0 , 
 
			
				
				
			
		
	
		
		
			
				
					
					    if ( enable  = =  true ) 
    SEED_CONFIG_TARGET  =  1 , 
 
			
				
				
			
		
	
		
		
			
				
					
					    { 
} ;  
			
				
				
			
		
	
		
		
			
				
					
					        if ( Core : : getInstance ( ) . isWorldLoaded ( ) ) 
 
			
		
	
		
		
			
				
					
					        { 
 
			
		
	
		
		
			
				
					
					            running  =  true ; 
 
			
		
	
		
		
			
				
					
					            out . print ( " seedwatch supervision started. \n " ) ; 
 
			
		
	
		
		
			
				
					
					        }  else  { 
 
			
		
	
		
		
			
				
					
					            out . printerr ( 
 
			
		
	
		
		
			
				
					
					                " This plugin needs a fortress to be loaded and will deactivate automatically otherwise. \n " 
 
			
		
	
		
		
			
				
					
					                " Activate with 'seedwatch start' after you load the game. \n " 
 
			
		
	
		
		
			
				
					
					                ) ; 
 
			
		
	
		
		
			
				
					
					        } 
 
			
		
	
		
		
			
				
					
					    }  else  { 
 
			
		
	
		
		
			
				
					
					        running  =  false ; 
 
			
		
	
		
		
			
				
					
					        out . print ( " seedwatch supervision stopped. \n " ) ; 
 
			
		
	
		
		
			
				
					
					    } 
 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    return  CR_OK ; 
static  int  get_config_val ( PersistentDataItem  & c ,  int  index )  {  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					    if  ( ! c . isValid ( ) ) 
 
			
		
	
		
		
			
				
					
					        return  - 1 ; 
 
			
		
	
		
		
			
				
					
					    return  c . ival ( index ) ; 
 
			
		
	
		
		
			
				
					
					}  
			
		
	
		
		
			
				
					
					static  bool  get_config_bool ( PersistentDataItem  & c ,  int  index )  {  
			
		
	
		
		
			
				
					
					    return  get_config_val ( c ,  index )  = =  1 ; 
 
			
		
	
		
		
			
				
					
					}  
			
		
	
		
		
			
				
					
					static  void  set_config_val ( PersistentDataItem  & c ,  int  index ,  int  value )  {  
			
		
	
		
		
			
				
					
					    if  ( c . isValid ( ) ) 
 
			
		
	
		
		
			
				
					
					        c . ival ( index )  =  value ; 
 
			
		
	
		
		
			
				
					
					}  
			
		
	
		
		
			
				
					
					static  void  set_config_bool ( PersistentDataItem  & c ,  int  index ,  bool  value )  {  
			
		
	
		
		
			
				
					
					    set_config_val ( c ,  index ,  value  ?  1  :  0 ) ; 
 
			
		
	
		
		
			
				
					
					} }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					command_result  df_seedwatch ( color_ostream  & out ,  vector < string > &  parameters ) static  PersistentDataItem  &  ensure_seed_config ( color_ostream  & out ,  int  id )  {  
			
				
				
			
		
	
		
		
			
				
					
					{     if  ( watched_seeds . count ( id ) ) 
 
			
				
				
			
		
	
		
		
			
				
					
					    CoreSuspender  suspend ; 
        return  watched_seeds [ id ] ; 
 
			
				
				
			
		
	
		
		
			
				
					
					
    string  keyname  =  SEED_CONFIG_KEY_PREFIX  +  int_to_string ( id ) ; 
 
			
				
				
			
		
	
		
		
			
				
					
					    map < string ,  int32_t >  plantIDs ; 
    DEBUG ( config , out ) . print ( " creating new persistent key for seed type %d \n " ,  id ) ; 
 
			
				
				
			
		
	
		
		
			
				
					
					    for ( size_t  i  =  0 ;  i  <  world - > raws . plants . all . size ( ) ;  + + i ) 
    watched_seeds . emplace ( id ,  World : : GetPersistentData ( keyname ,  NULL ) ) ; 
 
			
				
				
			
		
	
		
		
			
				
					
					    { 
    return  watched_seeds [ id ] ; 
 
			
				
				
			
		
	
		
		
			
				
					
					        auto  &  plant  =  world - > raws . plants . all [ i ] ; 
}  
			
				
				
			
		
	
		
		
			
				
					
					        if  ( plant - > material_defs . type [ plant_material_def : : seed ]  ! =  - 1 ) 
static  void  remove_seed_config ( color_ostream  & out ,  int  id )  {  
			
				
				
			
		
	
		
		
			
				
					
					            plantIDs [ plant - > id ]  =  i ; 
    if  ( ! watched_seeds . count ( id ) ) 
 
			
				
				
			
		
	
		
		
			
				
					
					    } 
        return ; 
 
			
				
				
			
		
	
		
		
			
				
					
					
    DEBUG ( config , out ) . print ( " removing persistent key for seed type %d \n " ,  id ) ; 
 
			
				
				
			
		
	
		
		
			
				
					
					    t_gamemodes  gm ; 
    World : : DeletePersistentData ( watched_seeds [ id ] ) ; 
 
			
				
				
			
		
	
		
		
			
				
					
					    World : : ReadGameMode ( gm ) ; // FIXME: check return value
 
    watched_seeds . erase ( id ) ; 
 
			
				
				
			
		
	
		
		
			
				
					
					
}  
			
				
				
			
		
	
		
		
			
				
					
					    // if game mode isn't fortress mode
 
 
			
		
	
		
		
			
				
					
					    if ( gm . g_mode  ! =  game_mode : : DWARF  | |  ! World : : isFortressMode ( gm . g_type ) ) 
 
			
		
	
		
		
			
				
					
					    { 
 
			
		
	
		
		
			
				
					
					        // just print the help
 
 
			
		
	
		
		
			
				
					
					        return  CR_WRONG_USAGE ; 
 
			
		
	
		
		
			
				
					
					    } 
 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    string  par ; 
static  const  int32_t  CYCLE_TICKS  =  1200 ;  
			
				
				
			
		
	
		
		
			
				
					
					    int  limit ; 
static  int32_t  cycle_timestamp  =  0 ;   // world->frame_counter at last cycle
  
			
				
				
			
		
	
		
		
			
				
					
					    switch ( parameters . size ( ) ) 
 
			
		
	
		
		
			
				
					
					    { 
 
			
		
	
		
		
			
				
					
					    case  0 : 
 
			
		
	
		
		
			
				
					
					        return  CR_WRONG_USAGE ; 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    case  1 : 
 
			
		
	
		
		
			
				
					
					        par  =  parameters [ 0 ] ; 
 
			
		
	
		
		
			
				
					
					        if  ( ( par  = =  " help " )  | |  ( par  = =  " ? " ) ) 
 
			
		
	
		
		
			
				
					
					        { 
 
			
		
	
		
		
			
				
					
					            return  CR_WRONG_USAGE ; 
 
			
		
	
		
		
			
				
					
					        } 
 
			
		
	
		
		
			
				
					
					        else  if ( par  = =  " start " ) 
 
			
		
	
		
		
			
				
					
					        { 
 
			
		
	
		
		
			
				
					
					            plugin_enable ( out ,  true ) ; 
 
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					        } 
static  command_result  do_command ( color_ostream  & out ,  vector < string >  & parameters ) ;  
			
				
				
			
		
	
		
		
			
				
					
					        else  if ( par  = =  " stop " ) 
static  void  do_cycle ( color_ostream  & out ,  int32_t  * num_enabled_seeds ,  int32_t  * num_disabled_seeds ) ;  
			
				
				
			
		
	
		
		
			
				
					
					        { 
static  void  seedwatch_setTarget ( color_ostream  & out ,  string  name ,  int32_t  num ) ;  
			
				
				
			
		
	
		
		
			
				
					
					            plugin_enable ( out ,  false ) ; 
 
			
		
	
		
		
			
				
					
					        } 
 
			
		
	
		
		
			
				
					
					        else  if ( par  = =  " clear " ) 
 
			
		
	
		
		
			
				
					
					        { 
 
			
		
	
		
		
			
				
					
					            Kitchen : : clearLimits ( ) ; 
 
			
		
	
		
		
			
				
					
					            out . print ( " seedwatch watchlist cleared \n " ) ; 
 
			
		
	
		
		
			
				
					
					        } 
 
			
		
	
		
		
			
				
					
					        else  if ( par  = =  " info " ) 
 
			
		
	
		
		
			
				
					
					        { 
 
			
		
	
		
		
			
				
					
					            out . print ( " seedwatch Info: \n " ) ; 
 
			
		
	
		
		
			
				
					
					            if ( running ) 
 
			
		
	
		
		
			
				
					
					            { 
 
			
		
	
		
		
			
				
					
					                out . print ( " seedwatch is supervising.  Use 'disable seedwatch' to stop supervision. \n " ) ; 
 
			
		
	
		
		
			
				
					
					            } 
 
			
		
	
		
		
			
				
					
					            else 
 
			
		
	
		
		
			
				
					
					            { 
 
			
		
	
		
		
			
				
					
					                out . print ( " seedwatch is not supervising.  Use 'enable seedwatch' to start supervision. \n " ) ; 
 
			
		
	
		
		
			
				
					
					            } 
 
			
		
	
		
		
			
				
					
					            map < int32_t ,  int16_t >  watchMap ; 
 
			
		
	
		
		
			
				
					
					            Kitchen : : fillWatchMap ( watchMap ) ; 
 
			
		
	
		
		
			
				
					
					            if ( watchMap . empty ( ) ) 
 
			
		
	
		
		
			
				
					
					            { 
 
			
		
	
		
		
			
				
					
					                out . print ( " The watch list is empty. \n " ) ; 
 
			
		
	
		
		
			
				
					
					            } 
 
			
		
	
		
		
			
				
					
					            else 
 
			
		
	
		
		
			
				
					
					            { 
 
			
		
	
		
		
			
				
					
					                out . print ( " The watch list is: \n " ) ; 
 
			
		
	
		
		
			
				
					
					                for ( auto  i  =  watchMap . begin ( ) ;  i  ! =  watchMap . end ( ) ;  + + i ) 
 
			
		
	
		
		
			
				
					
					                { 
 
			
		
	
		
		
			
				
					
					                    out . print ( " %s : %u \n " ,  world - > raws . plants . all [ i - > first ] - > id . c_str ( ) ,  i - > second ) ; 
 
			
		
	
		
		
			
				
					
					                } 
 
			
		
	
		
		
			
				
					
					            } 
 
			
		
	
		
		
			
				
					
					        } 
 
			
		
	
		
		
			
				
					
					        else  if ( par  = =  " debug " ) 
 
			
		
	
		
		
			
				
					
					        { 
 
			
		
	
		
		
			
				
					
					            map < int32_t ,  int16_t >  watchMap ; 
 
			
		
	
		
		
			
				
					
					            Kitchen : : fillWatchMap ( watchMap ) ; 
 
			
		
	
		
		
			
				
					
					            Kitchen : : debug_print ( out ) ; 
 
			
		
	
		
		
			
				
					
					        } 
 
			
		
	
		
		
			
				
					
					        else 
 
			
		
	
		
		
			
				
					
					        { 
 
			
		
	
		
		
			
				
					
					            string  token  =  searchAbbreviations ( par ) ; 
 
			
		
	
		
		
			
				
					
					            if ( plantIDs . count ( token )  >  0 ) 
 
			
		
	
		
		
			
				
					
					            { 
 
			
		
	
		
		
			
				
					
					                Kitchen : : removeLimit ( plantIDs [ token ] ) ; 
 
			
		
	
		
		
			
				
					
					                out . print ( " %s is not being watched \n " ,  token . c_str ( ) ) ; 
 
			
		
	
		
		
			
				
					
					            } 
 
			
		
	
		
		
			
				
					
					            else 
 
			
		
	
		
		
			
				
					
					            { 
 
			
		
	
		
		
			
				
					
					                out . print ( " %s has not been found as a material. \n " ,  token . c_str ( ) ) ; 
 
			
		
	
		
		
			
				
					
					            } 
 
			
		
	
		
		
			
				
					
					        } 
 
			
		
	
		
		
			
				
					
					        break ; 
 
			
		
	
		
		
			
				
					
					    case  2 : 
 
			
		
	
		
		
			
				
					
					        limit  =  atoi ( parameters [ 1 ] . c_str ( ) ) ; 
 
			
		
	
		
		
			
				
					
					        if ( limit  <  0 )  limit  =  0 ; 
 
			
		
	
		
		
			
				
					
					        if ( parameters [ 0 ]  = =  " all " ) 
 
			
		
	
		
		
			
				
					
					        { 
 
			
		
	
		
		
			
				
					
					            for ( auto  &  entry  :  plantIDs ) 
 
			
		
	
		
		
			
				
					
					                Kitchen : : setLimit ( entry . second ,  limit ) ; 
 
			
		
	
		
		
			
				
					
					        } 
 
			
		
	
		
		
			
				
					
					        else 
 
			
		
	
		
		
			
				
					
					        { 
 
			
		
	
		
		
			
				
					
					            string  token  =  searchAbbreviations ( parameters [ 0 ] ) ; 
 
			
		
	
		
		
			
				
					
					            if ( plantIDs . count ( token )  >  0 ) 
 
			
		
	
		
		
			
				
					
					            { 
 
			
		
	
		
		
			
				
					
					                Kitchen : : setLimit ( plantIDs [ token ] ,  limit ) ; 
 
			
		
	
		
		
			
				
					
					                out . print ( " %s is being watched. \n " ,  token . c_str ( ) ) ; 
 
			
		
	
		
		
			
				
					
					            } 
 
			
		
	
		
		
			
				
					
					            else 
 
			
		
	
		
		
			
				
					
					            { 
 
			
		
	
		
		
			
				
					
					                out . print ( " %s has not been found as a material. \n " ,  token . c_str ( ) ) ; 
 
			
		
	
		
		
			
				
					
					            } 
 
			
		
	
		
		
			
				
					
					        } 
 
			
		
	
		
		
			
				
					
					        break ; 
 
			
		
	
		
		
			
				
					
					    default : 
 
			
		
	
		
		
			
				
					
					        return  CR_WRONG_USAGE ; 
 
			
		
	
		
		
			
				
					
					        break ; 
 
			
		
	
		
		
			
				
					
					    } 
 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    return  CR_OK ;  DFhackCExport  command_result  plugin_init ( color_ostream  & out ,  std : : vector  < PluginCommand >  & commands )  {  
			
				
				
			
		
	
		
		
			
				
					
					}     DEBUG ( config , out ) . print ( " initializing %s \n " ,  plugin_name ) ; 
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					DFhackCExport  command_result  plugin_init ( color_ostream  & out ,  vector < PluginCommand > &  commands )     // provide a configuration interface for the plugin
 
 
			
				
				
			
		
	
		
		
			
				
					
					{  
			
		
	
		
		
	
		
		
			
				
					
					    commands . push_back ( PluginCommand ( 
    commands . push_back ( PluginCommand ( 
 
			
		
	
		
		
			
				
					
					        " seedwatch " , 
        plugin_name , 
 
			
				
				
			
		
	
		
		
			
				
					
					        " Toggles seed cooking based on quantity available. " , 
        " Automatically toggle seed cooking based on quantity available. " , 
 
			
				
				
			
		
	
		
		
			
				
					
					        df_seedwatch ) ) ; 
        do_command ) ) ; 
 
			
				
				
			
		
	
		
		
			
				
					
					    // fill in the abbreviations map, with abbreviations for the standard plants
 
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					    // fill in the abbreviations map
 
 
			
		
	
		
		
			
				
					
					    abbreviations [ " bs " ]  =  " SLIVER_BARB " ; 
    abbreviations [ " bs " ]  =  " SLIVER_BARB " ; 
 
			
		
	
		
		
			
				
					
					    abbreviations [ " bt " ]  =  " TUBER_BLOATED " ; 
    abbreviations [ " bt " ]  =  " TUBER_BLOATED " ; 
 
			
		
	
		
		
			
				
					
					    abbreviations [ " bw " ]  =  " WEED_BLADE " ; 
    abbreviations [ " bw " ]  =  " WEED_BLADE " ; 
 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -237,72 +133,283 @@ DFhackCExport command_result plugin_init(color_ostream &out, vector<PluginComman
 
			
		
	
		
		
			
				
					
					    abbreviations [ " vh " ]  =  " HERB_VALLEY " ; 
    abbreviations [ " vh " ]  =  " HERB_VALLEY " ; 
 
			
		
	
		
		
			
				
					
					    abbreviations [ " ws " ]  =  " BERRIES_STRAW " ; 
    abbreviations [ " ws " ]  =  " BERRIES_STRAW " ; 
 
			
		
	
		
		
			
				
					
					    abbreviations [ " wv " ]  =  " VINE_WHIP " ; 
    abbreviations [ " wv " ]  =  " VINE_WHIP " ; 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    return  CR_OK ; 
    return  CR_OK ; 
 
			
		
	
		
		
			
				
					
					} }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					DFhackCExport  command_result  plugin_onstatechange ( color_ostream  & out ,  state_change_event  event ) DFhackCExport  command_result  plugin_enable ( color_ostream  & out ,  bool  enable )  {  
			
				
				
			
		
	
		
		
			
				
					
					{     if  ( ! Core : : getInstance ( ) . isWorldLoaded ( ) )  { 
 
			
				
				
			
		
	
		
		
			
				
					
					    if  ( event  = =  SC_MAP_UNLOADED )  { 
        out . printerr ( " Cannot enable %s without a loaded world. \n " ,  plugin_name ) ; 
 
			
				
				
			
		
	
		
		
			
				
					
					        if  ( running ) 
        return  CR_FAILURE ; 
 
			
				
				
			
		
	
		
		
			
				
					
					            out . print ( " seedwatch deactivated due to game unload \n " ) ; 
 
			
		
	
		
		
			
				
					
					        running  =  false ; 
 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					    } 
    } 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    if  ( enable  ! =  is_enabled )  { 
 
			
		
	
		
		
			
				
					
					        is_enabled  =  enable ; 
 
			
		
	
		
		
			
				
					
					        DEBUG ( config , out ) . print ( " %s from the API; persisting \n " , 
 
			
		
	
		
		
			
				
					
					                                is_enabled  ?  " enabled "  :  " disabled " ) ; 
 
			
		
	
		
		
			
				
					
					        set_config_bool ( config ,  CONFIG_IS_ENABLED ,  is_enabled ) ; 
 
			
		
	
		
		
			
				
					
					        if  ( enable ) 
 
			
		
	
		
		
			
				
					
					            seedwatch_setTarget ( out ,  " all " ,  DEFAULT_TARGET ) ; 
 
			
		
	
		
		
			
				
					
					    }  else  { 
 
			
		
	
		
		
			
				
					
					        DEBUG ( config , out ) . print ( " %s from the API, but already %s; no action \n " , 
 
			
		
	
		
		
			
				
					
					                                is_enabled  ?  " enabled "  :  " disabled " , 
 
			
		
	
		
		
			
				
					
					                                is_enabled  ?  " enabled "  :  " disabled " ) ; 
 
			
		
	
		
		
			
				
					
					    } 
 
			
		
	
		
		
			
				
					
					    return  CR_OK ; 
    return  CR_OK ; 
 
			
		
	
		
		
			
				
					
					} }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					DFhackCExport  command_result  plugin_onupdate ( color_ostream  & out ) DFhackCExport  command_result  plugin_shutdown  ( color_ostream  & out )  {  
			
				
				
			
		
	
		
		
			
				
					
					{     DEBUG ( config , out ) . print ( " shutting down %s \n " ,  plugin_name ) ; 
 
			
				
				
			
		
	
		
		
			
				
					
					    if  ( running ) 
 
			
				
				
			
		
	
		
		
			
				
					
					    { 
 
			
		
	
		
		
			
				
					
					        // reduce processing rate
 
 
			
		
	
		
		
			
				
					
					        static  int  counter  =  0 ; 
 
			
		
	
		
		
			
				
					
					        if  ( + + counter  <  500 ) 
 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					    return  CR_OK ; 
    return  CR_OK ; 
 
			
		
	
		
		
			
				
					
					        counter  =  0 ; 
}  
			
				
				
			
		
	
		
		
			
				
					
					
 
			
				
				
			
		
	
		
		
			
				
					
					        t_gamemodes  gm ; 
DFhackCExport  command_result  plugin_load_data  ( color_ostream  & out )  {  
			
				
				
			
		
	
		
		
			
				
					
					        World : : ReadGameMode ( gm ) ; // FIXME: check return value
 
    world_plant_ids . clear ( ) ; 
 
			
				
				
			
		
	
		
		
			
				
					
					        // if game mode isn't fortress mode
 
    for  ( size_t  i  =  0 ;  i  <  world - > raws . plants . all . size ( ) ;  + + i )  { 
 
			
				
				
			
		
	
		
		
			
				
					
					        if ( gm . g_mode  ! =  game_mode : : DWARF  | |  ! World : : isFortressMode ( gm . g_type ) ) 
        auto  &  plant  =  world - > raws . plants . all [ i ] ; 
 
			
				
				
			
		
	
		
		
			
				
					
					        { 
        if  ( plant - > material_defs . type [ plant_material_def : : seed ]  ! =  - 1 ) 
 
			
				
				
			
		
	
		
		
			
				
					
					            // stop running.
 
            world_plant_ids [ plant - > id ]  =  i ; 
 
			
				
				
			
		
	
		
		
			
				
					
					            running  =  false ; 
    } 
 
			
				
				
			
		
	
		
		
			
				
					
					            out . printerr ( " seedwatch deactivated due to game mode switch \n " ) ; 
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					    config  =  World : : GetPersistentData ( CONFIG_KEY ) ; 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    if  ( ! config . isValid ( ) )  { 
 
			
		
	
		
		
			
				
					
					        DEBUG ( config , out ) . print ( " no config found in this save; initializing \n " ) ; 
 
			
		
	
		
		
			
				
					
					        config  =  World : : AddPersistentData ( CONFIG_KEY ) ; 
 
			
		
	
		
		
			
				
					
					        set_config_bool ( config ,  CONFIG_IS_ENABLED ,  is_enabled ) ; 
 
			
		
	
		
		
			
				
					
					    } 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    is_enabled  =  get_config_bool ( config ,  CONFIG_IS_ENABLED ) ; 
 
			
		
	
		
		
			
				
					
					    DEBUG ( config , out ) . print ( " loading persisted enabled state: %s \n " , 
 
			
		
	
		
		
			
				
					
					                            is_enabled  ?  " true "  :  " false " ) ; 
 
			
		
	
		
		
			
				
					
					    watched_seeds . clear ( ) ; 
 
			
		
	
		
		
			
				
					
					    vector < PersistentDataItem >  seed_configs ; 
 
			
		
	
		
		
			
				
					
					    World : : GetPersistentData ( & seed_configs ,  SEED_CONFIG_KEY_PREFIX ,  true ) ; 
 
			
		
	
		
		
			
				
					
					    const  size_t  num_seed_configs  =  seed_configs . size ( ) ; 
 
			
		
	
		
		
			
				
					
					    for  ( size_t  idx  =  0 ;  idx  <  num_seed_configs ;  + + idx )  { 
 
			
		
	
		
		
			
				
					
					        auto  & c  =  seed_configs [ idx ] ; 
 
			
		
	
		
		
			
				
					
					        watched_seeds . emplace ( get_config_val ( c ,  SEED_CONFIG_ID ) ,  c ) ; 
 
			
		
	
		
		
			
				
					
					    } 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    return  CR_OK ; 
 
			
		
	
		
		
			
				
					
					}  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					DFhackCExport  command_result  plugin_onstatechange ( color_ostream  & out ,  state_change_event  event )  {  
			
		
	
		
		
			
				
					
					    if  ( event  = =  DFHack : : SC_WORLD_UNLOADED )  { 
 
			
		
	
		
		
			
				
					
					        if  ( is_enabled )  { 
 
			
		
	
		
		
			
				
					
					            DEBUG ( config , out ) . print ( " world unloaded; disabling %s \n " , 
 
			
		
	
		
		
			
				
					
					                                    plugin_name ) ; 
 
			
		
	
		
		
			
				
					
					            is_enabled  =  false ; 
 
			
		
	
		
		
			
				
					
					        } 
 
			
		
	
		
		
			
				
					
					    } 
 
			
		
	
		
		
			
				
					
					    return  CR_OK ; 
    return  CR_OK ; 
 
			
		
	
		
		
			
				
					
					}  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					DFhackCExport  command_result  plugin_onupdate ( color_ostream  & out )  {  
			
		
	
		
		
			
				
					
					    if  ( is_enabled  & &  world - > frame_counter  -  cycle_timestamp  > =  CYCLE_TICKS )  { 
 
			
		
	
		
		
			
				
					
					        int32_t  num_enabled_seeds ,  num_disabled_seeds ; 
 
			
		
	
		
		
			
				
					
					        do_cycle ( out ,  & num_enabled_seeds ,  & num_disabled_seeds ) ; 
 
			
		
	
		
		
			
				
					
					        if  ( 0  <  num_enabled_seeds ) 
 
			
		
	
		
		
			
				
					
					            out . print ( " %s: enabled %d seed types for cooking \n " , 
 
			
		
	
		
		
			
				
					
					                    plugin_name ,  num_enabled_seeds ) ; 
 
			
		
	
		
		
			
				
					
					        if  ( 0  <  num_disabled_seeds ) 
 
			
		
	
		
		
			
				
					
					            out . print ( " %s: protected %d seed types from cooking \n " , 
 
			
		
	
		
		
			
				
					
					                    plugin_name ,  num_disabled_seeds ) ; 
 
			
		
	
		
		
			
				
					
					    } 
    } 
 
			
		
	
		
		
			
				
					
					        // this is dwarf mode, continue
 
    return  CR_OK ; 
 
			
				
				
			
		
	
		
		
			
				
					
					        map < int32_t ,  int16_t >  seedCount ;  // the number of seeds
 
}  
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					static  bool  call_seedwatch_lua ( color_ostream  * out ,  const  char  * fn_name ,  
			
		
	
		
		
			
				
					
					        int  nargs  =  0 ,  int  nres  =  0 , 
 
			
		
	
		
		
			
				
					
					        Lua : : LuaLambda  & &  args_lambda  =  Lua : : DEFAULT_LUA_LAMBDA , 
 
			
		
	
		
		
			
				
					
					        Lua : : LuaLambda  & &  res_lambda  =  Lua : : DEFAULT_LUA_LAMBDA )  { 
 
			
		
	
		
		
			
				
					
					    CoreSuspender  guard ; 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    auto  L  =  Lua : : Core : : State ; 
 
			
		
	
		
		
			
				
					
					    Lua : : StackUnwinder  top ( L ) ; 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    if  ( ! out ) 
 
			
		
	
		
		
			
				
					
					        out  =  & Core : : getInstance ( ) . getConsole ( ) ; 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    DEBUG ( config , * out ) . print ( " calling %s lua function: '%s' \n " ,  plugin_name ,  fn_name ) ; 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					        // count all seeds and plants by RAW material
 
    return  Lua : : CallLuaModuleFunction ( * out ,  L ,  " plugins.seedwatch " ,  fn_name , 
 
			
				
				
			
		
	
		
		
			
				
					
					        for ( size_t  i  =  0 ;  i  <  world - > items . other [ items_other_id : : SEEDS ] . size ( ) ;  + + i ) 
            nargs ,  nres , 
 
			
				
				
			
		
	
		
		
			
				
					
					        { 
            std : : forward < Lua : : LuaLambda & & > ( args_lambda ) , 
 
			
				
				
			
		
	
		
		
			
				
					
					            df : : item  * item  =  world - > items . other [ items_other_id : : SEEDS ] [ i ] ; 
            std : : forward < Lua : : LuaLambda & & > ( res_lambda ) ) ; 
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					}  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					static  command_result  do_command ( color_ostream  & out ,  vector < string >  & parameters )  {  
			
		
	
		
		
			
				
					
					    CoreSuspender  suspend ; 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    if  ( ! Core : : getInstance ( ) . isWorldLoaded ( ) )  { 
 
			
		
	
		
		
			
				
					
					        out . printerr ( " Cannot run %s without a loaded world. \n " ,  plugin_name ) ; 
 
			
		
	
		
		
			
				
					
					        return  CR_FAILURE ; 
 
			
		
	
		
		
			
				
					
					    } 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    bool  show_help  =  false ; 
 
			
		
	
		
		
			
				
					
					    if  ( ! call_seedwatch_lua ( & out ,  " parse_commandline " ,  parameters . size ( ) ,  1 , 
 
			
		
	
		
		
			
				
					
					            [ & ] ( lua_State  * L )  { 
 
			
		
	
		
		
			
				
					
					                for  ( const  string  & param  :  parameters ) 
 
			
		
	
		
		
			
				
					
					                    Lua : : Push ( L ,  param ) ; 
 
			
		
	
		
		
			
				
					
					            } , 
 
			
		
	
		
		
			
				
					
					            [ & ] ( lua_State  * L )  { 
 
			
		
	
		
		
			
				
					
					                show_help  =  ! lua_toboolean ( L ,  - 1 ) ; 
 
			
		
	
		
		
			
				
					
					            } ) )  { 
 
			
		
	
		
		
			
				
					
					        return  CR_FAILURE ; 
 
			
		
	
		
		
			
				
					
					    } 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    return  show_help  ?  CR_WRONG_USAGE  :  CR_OK ; 
 
			
		
	
		
		
			
				
					
					}  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					/////////////////////////////////////////////////////
  
			
		
	
		
		
			
				
					
					// cycle logic
  
			
		
	
		
		
			
				
					
					//
  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					struct  BadFlags  {  
			
		
	
		
		
			
				
					
					    uint32_t  whole ; 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    BadFlags ( )  { 
 
			
		
	
		
		
			
				
					
					        df : : item_flags  flags ; 
 
			
		
	
		
		
			
				
					
					        # define F(x) flags.bits.x = true; 
 
			
		
	
		
		
			
				
					
					        F ( dump ) ;  F ( forbid ) ;  F ( garbage_collect ) ; 
 
			
		
	
		
		
			
				
					
					        F ( hostile ) ;  F ( on_fire ) ;  F ( rotten ) ;  F ( trader ) ; 
 
			
		
	
		
		
			
				
					
					        F ( in_building ) ;  F ( construction ) ;  F ( artifact ) ; 
 
			
		
	
		
		
			
				
					
					        F ( in_job ) ;  F ( owned ) ;  F ( in_chest ) ;  F ( removed ) ; 
 
			
		
	
		
		
			
				
					
					        F ( encased ) ;  F ( spider_web ) ; 
 
			
		
	
		
		
			
				
					
					        # undef F 
 
			
		
	
		
		
			
				
					
					        whole  =  flags . whole ; 
 
			
		
	
		
		
			
				
					
					    } 
 
			
		
	
		
		
			
				
					
					} ;  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					static  bool  is_accessible_item ( df : : item  * item ,  const  vector < df : : unit  * >  & citizens )  {  
			
		
	
		
		
			
				
					
					    const  df : : coord  pos  =  Items : : getPosition ( item ) ; 
 
			
		
	
		
		
			
				
					
					    for  ( auto  & unit  :  citizens )  { 
 
			
		
	
		
		
			
				
					
					        if  ( Maps : : canWalkBetween ( Units : : getPosition ( unit ) ,  pos ) ) 
 
			
		
	
		
		
			
				
					
					            return  true ; 
 
			
		
	
		
		
			
				
					
					    } 
 
			
		
	
		
		
			
				
					
					    return  false ; 
 
			
		
	
		
		
			
				
					
					}  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					static  void  scan_seeds ( color_ostream  & out ,  unordered_map < int32_t ,  int32_t >  * accessible_counts ,  
			
		
	
		
		
			
				
					
					        unordered_map < int32_t ,  int32_t >  * inaccessible_counts  =  NULL )  { 
 
			
		
	
		
		
			
				
					
					    static  const  BadFlags  bad_flags ; 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    vector < df : : unit  * >  citizens ; 
 
			
		
	
		
		
			
				
					
					    Units : : getCitizens ( citizens ) ; 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    for  ( auto  & item  :  world - > items . other [ items_other_id : : SEEDS ] )  { 
 
			
		
	
		
		
			
				
					
					        MaterialInfo  mat ( item ) ; 
        MaterialInfo  mat ( item ) ; 
 
			
		
	
		
		
			
				
					
					        if  ( ! mat . isPlant ( ) ) 
        if  ( ! mat . isPlant ( ) ) 
 
			
		
	
		
		
			
				
					
					            continue ; 
            continue ; 
 
			
		
	
		
		
			
				
					
					            if  ( ! ignoreSeeds ( item - > flags ) ) 
        if  ( ( bad_flags . whole  &  item - > flags . whole )  | |  ! is_accessible_item ( item ,  citizens ) )  { 
 
			
				
				
			
		
	
		
		
			
				
					
					                + + seedCount [ mat . plant - > index ] ; 
            if  ( inaccessible_counts ) 
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					                + + ( * inaccessible_counts ) [ mat . plant - > index ] ; 
 
			
		
	
		
		
			
				
					
					        }  else  { 
 
			
		
	
		
		
			
				
					
					            if  ( accessible_counts ) 
 
			
		
	
		
		
			
				
					
					                + + ( * accessible_counts ) [ mat . plant - > index ] ; 
 
			
		
	
		
		
			
				
					
					        } 
 
			
		
	
		
		
			
				
					
					    } 
 
			
		
	
		
		
			
				
					
					}  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					static  void  do_cycle ( color_ostream  & out ,  int32_t  * num_enabled_seed_types ,  int32_t  * num_disabled_seed_types )  {  
			
		
	
		
		
			
				
					
					    DEBUG ( cycle , out ) . print ( " running %s cycle \n " ,  plugin_name ) ; 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    // mark that we have recently run
 
 
			
		
	
		
		
			
				
					
					    cycle_timestamp  =  world - > frame_counter ; 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    if  ( num_enabled_seed_types ) 
 
			
		
	
		
		
			
				
					
					        * num_enabled_seed_types  =  0 ; 
 
			
		
	
		
		
			
				
					
					    if  ( num_disabled_seed_types ) 
 
			
		
	
		
		
			
				
					
					        * num_disabled_seed_types  =  0 ; 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    unordered_map < int32_t ,  int32_t >  accessible_counts ; 
 
			
		
	
		
		
			
				
					
					    scan_seeds ( out ,  & accessible_counts ) ; 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    for  ( auto  & entry  :  watched_seeds )  { 
 
			
		
	
		
		
			
				
					
					        int32_t  id  =  entry . first ; 
 
			
		
	
		
		
			
				
					
					        int32_t  target  =  get_config_val ( entry . second ,  SEED_CONFIG_TARGET ) ; 
 
			
		
	
		
		
			
				
					
					        if  ( accessible_counts [ id ]  < =  target )  { 
 
			
		
	
		
		
			
				
					
					            DEBUG ( cycle , out ) . print ( " disabling seed mat: %d \n " ,  id ) ; 
 
			
		
	
		
		
			
				
					
					            if  ( num_disabled_seed_types ) 
 
			
		
	
		
		
			
				
					
					                + + * num_disabled_seed_types ; 
 
			
		
	
		
		
			
				
					
					            Kitchen : : denyPlantSeedCookery ( id ) ; 
 
			
		
	
		
		
			
				
					
					        }  else  if  ( target  +  TARGET_BUFFER  <  accessible_counts [ id ] )  { 
 
			
		
	
		
		
			
				
					
					            DEBUG ( cycle , out ) . print ( " enabling seed mat: %d \n " ,  id ) ; 
 
			
		
	
		
		
			
				
					
					            if  ( num_enabled_seed_types ) 
 
			
		
	
		
		
			
				
					
					                + + * num_enabled_seed_types ; 
 
			
		
	
		
		
			
				
					
					            Kitchen : : allowPlantSeedCookery ( id ) ; 
 
			
		
	
		
		
			
				
					
					        } 
 
			
		
	
		
		
			
				
					
					    } 
 
			
		
	
		
		
			
				
					
					}  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					/////////////////////////////////////////////////////
  
			
		
	
		
		
			
				
					
					// Lua API
  
			
		
	
		
		
			
				
					
					// core will already be suspended when coming in through here
  
			
		
	
		
		
			
				
					
					//
  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					static  void  set_target ( color_ostream  & out ,  int32_t  id ,  int32_t  target )  {  
			
		
	
		
		
			
				
					
					    if  ( target  = =  0 ) 
 
			
		
	
		
		
			
				
					
					        remove_seed_config ( out ,  id ) ; 
 
			
		
	
		
		
			
				
					
					    else  { 
 
			
		
	
		
		
			
				
					
					        PersistentDataItem  & c  =  ensure_seed_config ( out ,  id ) ; 
 
			
		
	
		
		
			
				
					
					        set_config_val ( c ,  SEED_CONFIG_TARGET ,  target ) ; 
 
			
		
	
		
		
			
				
					
					    } 
    } 
 
			
		
	
		
		
			
				
					
					}  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					        map < int32_t ,  int16_t >  watchMap ; 
// searches abbreviations, returns expansion if so, returns original if not
  
			
				
				
			
		
	
		
		
			
				
					
					        Kitchen : : fillWatchMap ( watchMap ) ; 
static  string  searchAbbreviations ( string  in )  {  
			
				
				
			
		
	
		
		
			
				
					
					        for ( auto  i  =  watchMap . begin ( ) ;  i  ! =  watchMap . end ( ) ;  + + i ) 
    if ( abbreviations . count ( in )  >  0 ) 
 
			
				
				
			
		
	
		
		
			
				
					
					        { 
        return  abbreviations [ in ] ; 
 
			
				
				
			
		
	
		
		
			
				
					
					            if ( seedCount [ i - > first ]  < =  i - > second ) 
    return  in ; 
 
			
				
				
			
		
	
		
		
			
				
					
					            { 
} ;  
			
				
				
			
		
	
		
		
			
				
					
					                Kitchen : : denyPlantSeedCookery ( i - > first ) ; 
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					static  void  seedwatch_setTarget ( color_ostream  & out ,  string  name ,  int32_t  num )  {  
			
		
	
		
		
			
				
					
					    DEBUG ( config , out ) . print ( " entering seedwatch_setTarget \n " ) ; 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    if  ( num  <  0 )  { 
 
			
		
	
		
		
			
				
					
					        out . printerr ( " target must be at least 0 \n " ) ; 
 
			
		
	
		
		
			
				
					
					        return ; 
 
			
		
	
		
		
			
				
					
					    } 
    } 
 
			
		
	
		
		
			
				
					
					            else  if ( i - > second  +  buffer  <  seedCount [ i - > first ] ) 
 
			
				
				
			
		
	
		
		
			
				
					
					            { 
    if  ( name  = =  " all " )  { 
 
			
				
				
			
		
	
		
		
			
				
					
					                Kitchen : : allowPlantSeedCookery ( i - > first ) ; 
        for  ( auto  & entry  :  world_plant_ids )  { 
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					            set_target ( out ,  entry . second ,  num ) ; 
 
			
		
	
		
		
			
				
					
					        } 
        } 
 
			
		
	
		
		
			
				
					
					        return ; 
 
			
		
	
		
		
			
				
					
					    } 
    } 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    string  token  =  searchAbbreviations ( name ) ; 
 
			
		
	
		
		
			
				
					
					    if  ( ! world_plant_ids . count ( token ) )  { 
 
			
		
	
		
		
			
				
					
					        out . printerr ( " %s has not been found as a material. \n " ,  token . c_str ( ) ) ; 
 
			
		
	
		
		
			
				
					
					        return ; 
 
			
		
	
		
		
			
				
					
					    } 
    } 
 
			
		
	
		
		
			
				
					
					    return  CR_OK ; 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					    set_target ( out ,  world_plant_ids [ token ] ,  num ) ; 
 
			
		
	
		
		
			
				
					
					} }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					DFhackCExport  command_result  plugin_shutdown ( Core *  pCore ) static  int  seedwatch_getData ( lua_State  * L )  {  
			
				
				
			
		
	
		
		
			
				
					
					{     color_ostream  * out  =  Lua : : GetOutput ( L ) ; 
 
			
				
				
			
		
	
		
		
			
				
					
					    return  CR_OK ; 
    if  ( ! out ) 
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					        out  =  & Core : : getInstance ( ) . getConsole ( ) ; 
 
			
		
	
		
		
			
				
					
					    DEBUG ( config , * out ) . print ( " entering seedwatch_getData \n " ) ; 
 
			
		
	
		
		
			
				
					
					    unordered_map < int32_t ,  int32_t >  watch_map ,  accessible_counts ; 
 
			
		
	
		
		
			
				
					
					    scan_seeds ( * out ,  & accessible_counts ) ; 
 
			
		
	
		
		
			
				
					
					    for  ( auto  & entry  :  watched_seeds )  { 
 
			
		
	
		
		
			
				
					
					        watch_map . emplace ( entry . first ,  get_config_val ( entry . second ,  SEED_CONFIG_TARGET ) ) ; 
 
			
		
	
		
		
			
				
					
					    } 
 
			
		
	
		
		
			
				
					
					    Lua : : Push ( L ,  watch_map ) ; 
 
			
		
	
		
		
			
				
					
					    Lua : : Push ( L ,  accessible_counts ) ; 
 
			
		
	
		
		
			
				
					
					    return  2 ; 
 
			
		
	
		
		
			
				
					
					} }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					DFHACK_PLUGIN_LUA_FUNCTIONS  {  
			
		
	
		
		
			
				
					
					    DFHACK_LUA_FUNCTION ( seedwatch_setTarget ) , 
 
			
		
	
		
		
			
				
					
					    DFHACK_LUA_END 
 
			
		
	
		
		
			
				
					
					} ;  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					DFHACK_PLUGIN_LUA_COMMANDS  {  
			
		
	
		
		
			
				
					
					    DFHACK_LUA_COMMAND ( seedwatch_getData ) , 
 
			
		
	
		
		
			
				
					
					    DFHACK_LUA_END 
 
			
		
	
		
		
			
				
					
					} ;