|  |  | @ -22,6 +22,7 @@ | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | #include "df/building_axle_horizontalst.h" |  |  |  | #include "df/building_axle_horizontalst.h" | 
			
		
	
		
		
			
				
					
					|  |  |  | #include "df/building_bridgest.h" |  |  |  | #include "df/building_bridgest.h" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | #include "df/building_civzonest.h" | 
			
		
	
		
		
			
				
					
					|  |  |  | #include "df/building_constructionst.h" |  |  |  | #include "df/building_constructionst.h" | 
			
		
	
		
		
			
				
					
					|  |  |  | #include "df/building_furnacest.h" |  |  |  | #include "df/building_furnacest.h" | 
			
		
	
		
		
			
				
					
					|  |  |  | #include "df/building_rollersst.h" |  |  |  | #include "df/building_rollersst.h" | 
			
		
	
	
		
		
			
				
					|  |  | @ -81,6 +82,7 @@ struct blueprint_options { | 
			
		
	
		
		
			
				
					
					|  |  |  |     bool track = false; |  |  |  |     bool track = false; | 
			
		
	
		
		
			
				
					
					|  |  |  |     bool build = false; |  |  |  |     bool build = false; | 
			
		
	
		
		
			
				
					
					|  |  |  |     bool place = false; |  |  |  |     bool place = false; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     bool zone  = false; | 
			
		
	
		
		
			
				
					
					|  |  |  |     bool query = false; |  |  |  |     bool query = false; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     static struct_identity _identity; |  |  |  |     static struct_identity _identity; | 
			
		
	
	
		
		
			
				
					|  |  | @ -101,6 +103,7 @@ static const struct_field_info blueprint_options_fields[] = { | 
			
		
	
		
		
			
				
					
					|  |  |  |     { struct_field_info::PRIMITIVE, "track",                  offsetof(blueprint_options, track),                 &df::identity_traits<bool>::identity,    0, 0 }, |  |  |  |     { struct_field_info::PRIMITIVE, "track",                  offsetof(blueprint_options, track),                 &df::identity_traits<bool>::identity,    0, 0 }, | 
			
		
	
		
		
			
				
					
					|  |  |  |     { struct_field_info::PRIMITIVE, "build",                  offsetof(blueprint_options, build),                 &df::identity_traits<bool>::identity,    0, 0 }, |  |  |  |     { struct_field_info::PRIMITIVE, "build",                  offsetof(blueprint_options, build),                 &df::identity_traits<bool>::identity,    0, 0 }, | 
			
		
	
		
		
			
				
					
					|  |  |  |     { struct_field_info::PRIMITIVE, "place",                  offsetof(blueprint_options, place),                 &df::identity_traits<bool>::identity,    0, 0 }, |  |  |  |     { struct_field_info::PRIMITIVE, "place",                  offsetof(blueprint_options, place),                 &df::identity_traits<bool>::identity,    0, 0 }, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     { struct_field_info::PRIMITIVE, "zone",                   offsetof(blueprint_options, zone),                  &df::identity_traits<bool>::identity,    0, 0 }, | 
			
		
	
		
		
			
				
					
					|  |  |  |     { struct_field_info::PRIMITIVE, "query",                  offsetof(blueprint_options, query),                 &df::identity_traits<bool>::identity,    0, 0 }, |  |  |  |     { struct_field_info::PRIMITIVE, "query",                  offsetof(blueprint_options, query),                 &df::identity_traits<bool>::identity,    0, 0 }, | 
			
		
	
		
		
			
				
					
					|  |  |  |     { struct_field_info::END } |  |  |  |     { struct_field_info::END } | 
			
		
	
		
		
			
				
					
					|  |  |  | }; |  |  |  | }; | 
			
		
	
	
		
		
			
				
					|  |  | @ -217,7 +220,7 @@ static const char * get_tile_track(const df::coord &pos, const tile_context &) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     return NULL; |  |  |  |     return NULL; | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | static pair<uint32_t, uint32_t> get_building_size(df::building *b) { |  |  |  | static pair<uint32_t, uint32_t> get_building_size(const df::building *b) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     return pair<uint32_t, uint32_t>(b->x2 - b->x1 + 1, b->y2 - b->y1 + 1); |  |  |  |     return pair<uint32_t, uint32_t>(b->x2 - b->x1 + 1, b->y2 - b->y1 + 1); | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -225,8 +228,8 @@ static const char * if_pretty(const tile_context &ctx, const char *c) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     return ctx.pretty ? c : NULL; |  |  |  |     return ctx.pretty ? c : NULL; | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | static bool is_rectangular(const tile_context &ctx) { |  |  |  | static bool is_rectangular(const df::building *bld) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     df::building_extents &room = ctx.b->room; |  |  |  |     const df::building_extents &room = bld->room; | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     if (!room.extents) |  |  |  |     if (!room.extents) | 
			
		
	
		
		
			
				
					
					|  |  |  |         return true; |  |  |  |         return true; | 
			
		
	
		
		
			
				
					
					|  |  |  |     for (int32_t y = 0; y < room.height; ++y) { |  |  |  |     for (int32_t y = 0; y < room.height; ++y) { | 
			
		
	
	
		
		
			
				
					|  |  | @ -238,6 +241,10 @@ static bool is_rectangular(const tile_context &ctx) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     return true; |  |  |  |     return true; | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | static bool is_rectangular(const tile_context &ctx) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     return is_rectangular(ctx.b); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | static const char * do_block_building(const tile_context &ctx, const char *s, |  |  |  | static const char * do_block_building(const tile_context &ctx, const char *s, | 
			
		
	
		
		
			
				
					
					|  |  |  |                                       bool at_target_pos, |  |  |  |                                       bool at_target_pos, | 
			
		
	
		
		
			
				
					
					|  |  |  |                                       bool *add_size = NULL) { |  |  |  |                                       bool *add_size = NULL) { | 
			
		
	
	
		
		
			
				
					|  |  | @ -614,16 +621,21 @@ static const char * get_build_keys(const df::coord &pos, | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | // returns "~" if keys is NULL; otherwise returns the keys with the building
 |  |  |  | // returns "~" if keys is NULL; otherwise returns the keys with the building
 | 
			
		
	
		
		
			
				
					
					|  |  |  | // dimensions in the expansion syntax
 |  |  |  | // dimensions in the expansion syntax
 | 
			
		
	
		
		
			
				
					
					|  |  |  | static const char * add_expansion_syntax(const tile_context &ctx, |  |  |  | static const char * add_expansion_syntax(const df::building *bld, | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |                                          const char *keys) { |  |  |  |                                          const char *keys) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (!keys) |  |  |  |     if (!keys) | 
			
		
	
		
		
			
				
					
					|  |  |  |         return "~"; |  |  |  |         return "~"; | 
			
		
	
		
		
			
				
					
					|  |  |  |     std::ostringstream s; |  |  |  |     std::ostringstream s; | 
			
		
	
		
		
			
				
					
					|  |  |  |     pair<uint32_t, uint32_t> size = get_building_size(ctx.b); |  |  |  |     pair<uint32_t, uint32_t> size = get_building_size(bld); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     s << keys << "(" << size.first << "x" << size.second << ")"; |  |  |  |     s << keys << "(" << size.first << "x" << size.second << ")"; | 
			
		
	
		
		
			
				
					
					|  |  |  |     return cache(s); |  |  |  |     return cache(s); | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | static const char * add_expansion_syntax(const tile_context &ctx, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                                          const char *keys) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     return add_expansion_syntax(ctx.b, keys); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | static const char * get_tile_build(const df::coord &pos, |  |  |  | static const char * get_tile_build(const df::coord &pos, | 
			
		
	
		
		
			
				
					
					|  |  |  |                                    const tile_context &ctx) { |  |  |  |                                    const tile_context &ctx) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (!ctx.b || ctx.b->getType() == building_type::Stockpile) { |  |  |  |     if (!ctx.b || ctx.b->getType() == building_type::Stockpile) { | 
			
		
	
	
		
		
			
				
					|  |  | @ -690,6 +702,113 @@ static const char * get_tile_place(const df::coord &pos, | 
			
		
	
		
		
			
				
					
					|  |  |  |     return add_expansion_syntax(ctx, get_place_keys(ctx)); |  |  |  |     return add_expansion_syntax(ctx, get_place_keys(ctx)); | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | static bool hospital_maximums_eq(const df::hospital_supplies &a, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                                  const df::hospital_supplies &b) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     return a.max_thread == b.max_thread && | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             a.max_cloth == b.max_cloth && | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             a.max_splints == b.max_splints && | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             a.max_crutches == b.max_crutches && | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             a.max_plaster == b.max_plaster && | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             a.max_buckets == b.max_buckets && | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             a.max_soap == b.max_soap; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | static const char * get_zone_keys(const df::building_civzonest *zone) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     static const uint32_t DEFAULT_GATHER_FLAGS = | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             df::building_civzonest::T_gather_flags::mask_pick_trees | | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             df::building_civzonest::T_gather_flags::mask_pick_shrubs | | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             df::building_civzonest::T_gather_flags::mask_gather_fallen; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     static const df::hospital_supplies DEFAULT_HOSPITAL; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     std::ostringstream keys; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     const df::building_civzonest::T_zone_flags &flags = zone->zone_flags; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     // inverted logic for Active since it's on by default
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if (!flags.bits.active) keys << 'a'; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     // in UI order
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if (flags.bits.water_source) keys << 'w'; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if (flags.bits.fishing) keys << 'f'; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if (flags.bits.gather) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         keys << 'g'; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if (zone->gather_flags.whole != DEFAULT_GATHER_FLAGS) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             keys << 'G'; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             // logic is inverted since they're all on by default
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             if (!zone->gather_flags.bits.pick_trees) keys << 't'; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             if (!zone->gather_flags.bits.pick_shrubs) keys << 's'; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             if (!zone->gather_flags.bits.gather_fallen) keys << 'f'; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             keys << '^'; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if (flags.bits.garbage_dump) keys << 'd'; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if (flags.bits.pen_pasture) keys << 'n'; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if (flags.bits.pit_pond) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         keys << 'p'; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if (zone->pit_flags.bits.is_pond) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             keys << "Pf^"; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if (flags.bits.sand) keys << 's'; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if (flags.bits.clay) keys << 'c'; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if (flags.bits.meeting_area) keys << 'm'; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if (flags.bits.hospital) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         keys << 'h'; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         const df::hospital_supplies &hospital = zone->hospital; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if (!hospital_maximums_eq(hospital, DEFAULT_HOSPITAL)) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             keys << "H{hospital"; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             if (hospital.max_thread != DEFAULT_HOSPITAL.max_thread) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 keys << " thread=" << hospital.max_thread; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             if (hospital.max_cloth != DEFAULT_HOSPITAL.max_cloth) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 keys << " cloth=" << hospital.max_cloth; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             if (hospital.max_splints != DEFAULT_HOSPITAL.max_splints) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 keys << " splints=" << hospital.max_splints; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             if (hospital.max_crutches != DEFAULT_HOSPITAL.max_crutches) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 keys << " crutches=" << hospital.max_crutches; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             if (hospital.max_plaster != DEFAULT_HOSPITAL.max_plaster) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 keys << " plaster=" << hospital.max_plaster; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             if (hospital.max_buckets != DEFAULT_HOSPITAL.max_buckets) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 keys << " buckets=" << hospital.max_buckets; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             if (hospital.max_soap != DEFAULT_HOSPITAL.max_soap) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 keys << " soap=" << hospital.max_soap; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             keys << "}^"; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if (flags.bits.animal_training) keys << 't'; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     string keys_str = keys.str(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     // there is no way to represent an active, but empty zone in quickfort
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if (keys_str.empty()) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         return NULL; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     // remove final '^' character if there is one
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if (keys_str.back() == '^') | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         keys_str.pop_back(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     return cache(keys_str); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | static const char * get_tile_zone(const df::coord &pos, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                                   const tile_context &ctx) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     vector<df::building_civzonest*> civzones; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if (!Buildings::findCivzonesAt(&civzones, pos)) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         return NULL; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     // we only have one "zone" blueprint, so use the "topmost" zone (that is,
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     // the one that is highlighted when the cursor is over this tile).
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     // overlapping zones are outside the scope of this plugin, I think.
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     df::building_civzonest *zone = civzones.back(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if (!is_rectangular(zone)) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         return get_zone_keys(zone); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if (zone->x1 != static_cast<int32_t>(pos.x) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             || zone->y1 != static_cast<int32_t>(pos.y)) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         return if_pretty(ctx, "`"); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     return add_expansion_syntax(zone, get_zone_keys(zone)); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | static const char * get_tile_query(const df::coord &, const tile_context &ctx) { |  |  |  | static const char * get_tile_query(const df::coord &, const tile_context &ctx) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (!ctx.b || !ctx.b->is_room) |  |  |  |     if (!ctx.b || !ctx.b->is_room) | 
			
		
	
		
		
			
				
					
					|  |  |  |         return NULL; |  |  |  |         return NULL; | 
			
		
	
	
		
		
			
				
					|  |  | @ -760,7 +879,7 @@ struct blueprint_processor { | 
			
		
	
		
		
			
				
					
					|  |  |  |     init_ctx_fn * const init_ctx; |  |  |  |     init_ctx_fn * const init_ctx; | 
			
		
	
		
		
			
				
					
					|  |  |  |     blueprint_processor(const string &mode, const string &phase, |  |  |  |     blueprint_processor(const string &mode, const string &phase, | 
			
		
	
		
		
			
				
					
					|  |  |  |                         bool force_create, get_tile_fn *get_tile, |  |  |  |                         bool force_create, get_tile_fn *get_tile, | 
			
		
	
		
		
			
				
					
					|  |  |  |                         init_ctx_fn *init_ctx = NULL) |  |  |  |                         init_ctx_fn *init_ctx) | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         : mode(mode), phase(phase), force_create(force_create), |  |  |  |         : mode(mode), phase(phase), force_create(force_create), | 
			
		
	
		
		
			
				
					
					|  |  |  |           get_tile(get_tile), init_ctx(init_ctx) { } |  |  |  |           get_tile(get_tile), init_ctx(init_ctx) { } | 
			
		
	
		
		
			
				
					
					|  |  |  | }; |  |  |  | }; | 
			
		
	
	
		
		
			
				
					|  |  | @ -865,6 +984,16 @@ static void ensure_building(const df::coord &pos, tile_context &ctx) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     ctx.b = Buildings::findAtTile(pos); |  |  |  |     ctx.b = Buildings::findAtTile(pos); | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | static void add_processor(vector<blueprint_processor> &processors, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                           const blueprint_options &opts, const char *mode, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                           const char *phase, bool require_phase, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                           get_tile_fn * const get_tile, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                           init_ctx_fn * const init_ctx = NULL) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if (opts.auto_phase || require_phase) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         processors.push_back(blueprint_processor(mode, phase, require_phase, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                                                  get_tile, init_ctx)); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | static bool do_transform(color_ostream &out, |  |  |  | static bool do_transform(color_ostream &out, | 
			
		
	
		
		
			
				
					
					|  |  |  |                          const df::coord &start, const df::coord &end, |  |  |  |                          const df::coord &start, const df::coord &end, | 
			
		
	
		
		
			
				
					
					|  |  |  |                          const blueprint_options &opts, |  |  |  |                          const blueprint_options &opts, | 
			
		
	
	
		
		
			
				
					|  |  | @ -875,21 +1004,15 @@ static bool do_transform(color_ostream &out, | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     vector<blueprint_processor> processors; |  |  |  |     vector<blueprint_processor> processors; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (opts.auto_phase || opts.dig) |  |  |  |     add_processor(processors, opts, "dig", "dig", opts.dig, get_tile_dig); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         processors.push_back(blueprint_processor("dig", "dig", opts.dig, |  |  |  |     add_processor(processors, opts, "dig", "track", opts.track, get_tile_track); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                                                  get_tile_dig)); |  |  |  |     add_processor(processors, opts, "build", "build", opts.build, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     if (opts.auto_phase || opts.track) |  |  |  |                   get_tile_build, ensure_building); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         processors.push_back(blueprint_processor("dig", "track", opts.track, |  |  |  |     add_processor(processors, opts, "place", "place", opts.place, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                                                  get_tile_track)); |  |  |  |                   get_tile_place, ensure_building); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     if (opts.auto_phase || opts.build) |  |  |  |     add_processor(processors, opts, "zone", "zone", opts.zone, get_tile_zone); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         processors.push_back(blueprint_processor("build", "build", opts.build, |  |  |  |     add_processor(processors, opts, "query", "query", opts.query, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                                             get_tile_build, ensure_building)); |  |  |  |                   get_tile_query, ensure_building); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     if (opts.auto_phase || opts.place) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         processors.push_back(blueprint_processor("place", "place", opts.place, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                                             get_tile_place, ensure_building)); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (opts.auto_phase || opts.query) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         processors.push_back(blueprint_processor("query", "query", opts.query, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                                             get_tile_query, ensure_building)); |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (processors.empty()) { |  |  |  |     if (processors.empty()) { | 
			
		
	
		
		
			
				
					
					|  |  |  |         out.printerr("no phases requested! nothing to do!\n"); |  |  |  |         out.printerr("no phases requested! nothing to do!\n"); | 
			
		
	
	
		
		
			
				
					|  |  | 
 |