The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
builder.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2004 - 2016 by Philippe Plantier <[email protected]>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 /**
16  * @file
17  * Terrain builder.
18  */
19 
20 #include "terrain/builder.hpp"
21 
22 #include "game_preferences.hpp"
23 #include "image.hpp"
24 #include "log.hpp"
25 #include "map/map.hpp"
28 
29 static lg::log_domain log_engine("engine");
30 #define ERR_NG LOG_STREAM(err, log_engine)
31 #define WRN_NG LOG_STREAM(warn, log_engine)
32 
33 /**
34  *
35  * These legacy map_location functions moved here from map_location.?pp.
36  * We have refactored them out of everything but this class. Hopefully
37  * the end is near...
38  *
39  // Adds an absolute location to a "delta" location
40  // This is not the mathematically correct behavior, it is neither
41  // commutative nor associative. Negative coordinates may give strange
42  // results. It is retained because terrain builder code relies in this
43  // broken behavior. Best avoid.
44  map_location legacy_negation() const;
45  map_location legacy_sum(const map_location &a) const;
46  map_location& legacy_sum_assign(const map_location &a);
47  map_location legacy_difference(const map_location &a) const;
48  *
49  */
50 
52 {
53  return map_location(-me.x, -me.y);
54 }
55 
57 {
58  bool parity = (me.x & 1) != 0;
59  me.x += a.x;
60  me.y += a.y;
61  if((a.x > 0) && (a.x % 2) && parity)
62  me.y++;
63  if((a.x < 0) && (a.x % 2) && !parity)
64  me.y--;
65 
66  return me;
67 }
68 
70 {
71  map_location ret(me);
72  legacy_sum_assign(ret,a);
73  return ret;
74 }
75 
77 {
78  return legacy_sum(me,legacy_negation(a));
79 }
80 
81 /**
82  *
83  * This file holds the terrain_builder implementation.
84  *
85  */
86 
88 const config* terrain_builder::rules_cfg_ = nullptr;
89 
90 terrain_builder::rule_image::rule_image(int layer, int x, int y, bool global_image, int cx, int cy, bool is_water) :
91  layer(layer),
92  basex(x),
93  basey(y),
94  variants(),
95  global_image(global_image),
96  center_x(cx),
97  center_y(cy),
98  is_water(is_water)
99 {}
100 
102  flags(),
103  images(),
104  images_foreground(),
105  images_background(),
106  last_tod("invalid_tod"),
107  sorted_images(false)
108 {}
109 
111 {
112  images_background.clear();
113  images_foreground.clear();
114 
115  if(!sorted_images){
116  //sort images by their layer (and basey)
117  //but use stable to keep the insertion order in equal cases
118  std::stable_sort(images.begin(), images.end());
119  sorted_images = true;
120  }
121 
122  for(const rule_image_rand& ri : images) {
123  bool is_background = ri->is_background();
124  bool animate = (!ri.ri->is_water || preferences::animate_water());
125 
126  imagelist& img_list = is_background ? images_background : images_foreground;
127 
128  for(const rule_image_variant& variant : ri->variants) {
129  if(!variant.has_flag.empty()) {
130  bool has_flag_match = true;
131  for(const std::string& s : variant.has_flag) {
132  // If a flag listed in "has_flag" is not present, this variant does not match
133  if(flags.find(s) == flags.end()) {
134  has_flag_match = false;
135  break;
136  }
137  }
138 
139  if(!has_flag_match) {
140  continue;
141  }
142  }
143 
144  if(!variant.tods.empty() && variant.tods.find(tod) == variant.tods.end())
145  continue;
146 
147  //need to break parity pattern in RNG
148  /** @todo improve this */
149  unsigned int rnd = ri.rand / 7919; //just the 1000th prime
150  const animated<image::locator>& anim = variant.images[rnd % variant.images.size()];
151 
152  bool is_empty = true;
153  for(size_t i = 0; i < anim.get_frames_count(); ++i) {
154  if(!image::is_empty_hex(anim.get_frame(i))) {
155  is_empty = false;
156  break;
157  }
158  }
159 
160  if(is_empty)
161  continue;
162 
163  img_list.push_back(anim);
164 
165  if(variant.random_start)
166  img_list.back().set_animation_time(ri.rand % img_list.back().get_animation_duration());
167 
168  if (!animate) {
169  img_list.back().pause_animation();
170  }
171 
172  if(log) {
173  log->push_back(std::make_pair(&ri, &variant));
174  }
175 
176  break; // found a matching variant
177  }
178  }
179 }
180 
182 {
183  flags.clear();
184  images.clear();
185  sorted_images = false;
186  images_foreground.clear();
187  images_background.clear();
188  last_tod = "invalid_tod";
189 }
190 
191 static unsigned int get_noise(const map_location& loc, unsigned int index){
192  unsigned int a = (loc.x + 92872973) ^ 918273;
193  unsigned int b = (loc.y + 1672517) ^ 128123;
194  unsigned int c = (index + 127390) ^ 13923787;
195  unsigned int abc = a*b*c + a*b + b*c + a*c + a + b + c;
196  return abc*abc;
197 }
198 
200 {
201  for(std::vector<tile>::iterator it = tiles_.begin(); it != tiles_.end(); ++it)
202  it->clear();
203 }
204 
206 {
207  x_ = x;
208  y_ = y;
209  std::vector<terrain_builder::tile> new_tiles((x + 4) * (y + 4));
210  tiles_.swap(new_tiles);
211  reset();
212 }
213 
215 {
216  if(loc.x < -2 || loc.y < -2 || loc.x > (x_ + 1) || loc.y > (y_ + 1)) {
217  return false;
218  }
219 
220  return true;
221 
222 }
223 
225 {
226  assert(on_map(loc));
227 
228  return tiles_[(loc.x + 2) + (loc.y + 2) * (x_ + 4)];
229 }
230 
232 {
233  assert(on_map(loc));
234 
235  return tiles_[(loc.x + 2) + (loc.y + 2) * (x_ + 4)];
236 }
237 
239  const gamemap* m, const std::string& offmap_image) :
241  map_(m),
242  tile_map_(m ? map().w() : 0, m ? map().h() :0),
244 {
245  image::precache_file_existence("terrain/");
246 
247  if(building_rules_.empty() && rules_cfg_){
248  //off_map first to prevent some default rule seems to block it
249  add_off_map_rule(offmap_image);
250  // parse global terrain rules
252  } else {
253  // use cached global rules but clear local rules
255  }
256 
257  // parse local rules
258  parse_config(level);
259 
260  if (m)
261  build_terrains();
262 }
263 
265 {
266  for(int x = -2; x <= map().w(); ++x) {
267  for(int y = -2; y <= map().h(); ++y) {
268  tile_map_[map_location(x,y)].rebuild_cache("");
269  }
270  }
271 }
272 
274 {
276  for(; i != building_rules_.end();){
277  if (i->local)
278  building_rules_.erase(i++);
279  else
280  ++i;
281  }
282 }
283 
285 {
286  rules_cfg_ = &cfg;
287  // use the swap trick to clear the rules cache and get a fresh one.
288  // because simple clear() seems to cause some progressive memory degradation.
289  building_ruleset empty;
290  std::swap(building_rules_, empty);
291 }
292 
294 {
295  tile_map_.reload(map().w(), map().h());
296  terrain_by_type_.clear();
297  build_terrains();
298 }
299 
301 {
302  map_ = m;
303  reload_map();
304 }
305 
307  const std::string &tod, const TERRAIN_TYPE terrain_type)
308 {
309  if(!tile_map_.on_map(loc))
310  return nullptr;
311 
312  tile& tile_at = tile_map_[loc];
313 
314  if(tod != tile_at.last_tod) {
315  tile_at.rebuild_cache(tod);
316  tile_at.last_tod = tod;
317  }
318 
319  const imagelist& img_list = (terrain_type == BACKGROUND) ?
320  tile_at.images_background : tile_at.images_foreground;
321 
322  if(!img_list.empty()) {
323  return &img_list;
324  }
325 
326  return nullptr;
327 }
328 
330 {
331  if(!tile_map_.on_map(loc))
332  return false;
333 
334  bool changed = false;
335 
336  tile& btile = tile_map_[loc];
337 
339  if(a.need_update())
340  changed = true;
342  }
344  if(a.need_update())
345  changed = true;
347  }
348 
349  return changed;
350 }
351 
352 /** @todo TODO: rename this function */
354 {
355  if (tile_map_.on_map(loc)) {
356  tile& btile = tile_map_[loc];
357  // btile.images.clear();
358  btile.images_foreground.clear();
359  btile.images_background.clear();
360  const std::string filename =
362 
363  if(!filename.empty()) {
364  animated<image::locator> img_loc;
365  img_loc.add_frame(100,image::locator("terrain/" + filename + ".png"));
366  img_loc.start_animation(0, true);
367  btile.images_background.push_back(img_loc);
368  }
369 
370  //Combine base and overlay image if necessary
371  if(map().get_terrain_info(loc).is_combined()) {
372  const std::string filename_ovl =
374 
375  if(!filename_ovl.empty()) {
376  animated<image::locator> img_loc_ovl;
377  img_loc_ovl.add_frame(100,image::locator("terrain/" + filename_ovl + ".png"));
378  img_loc_ovl.start_animation(0, true);
379  btile.images_background.push_back(img_loc_ovl);
380  }
381  }
382  }
383 }
384 
386 {
387  tile_map_.reset();
388  terrain_by_type_.clear();
389  build_terrains();
390 }
391 
392 static bool image_exists(const std::string& name)
393 {
394  bool precached = name.find("..") == std::string::npos;
395 
396  if(precached && image::precached_file_exists(name)) {
397  return true;
398  } else if(image::exists(name)) {
399  return true;
400  }
401 
402  return false;
403 }
404 
405 static std::vector<std::string> get_variations(const std::string& base, const std::string& variations)
406 {
407  /** @todo optimize this function */
408  std::vector<std::string> res;
409  if(variations.empty()){
410  res.push_back(base);
411  return res;
412  }
413  std::string::size_type pos = base.find("@V", 0);
414  if(pos == std::string::npos) {
415  res.push_back(base);
416  return res;
417  }
418  std::vector<std::string> vars = utils::split(variations, ';', 0);
419 
420  for (const std::string& v : vars) {
421  res.push_back(base);
422  std::string::size_type pos = 0;
423  while ((pos = res.back().find("@V", pos)) != std::string::npos) {
424  res.back().replace(pos, 2, v);
425  pos += v.size();
426  }
427  }
428  return res;
429 }
430 
432 {
433  // If the rule has no constraints, it is invalid
434  if(rule.constraints.empty())
435  return false;
436 
437  // Parse images and animations data
438  // If one is not valid, return false.
439  for(terrain_constraint &constraint : rule.constraints)
440  {
441  for(rule_image& ri : constraint.images)
442  {
444  {
445 
446  std::vector<std::string> var_strings = get_variations(variant.image_string, variant.variations);
447  for(const std::string& var : var_strings)
448  {
449  /** @todo improve this, 99% of terrains are not animated. */
450  std::vector<std::string> frames = utils::square_parenthetical_split(var,',');
452 
453  for(const std::string& frame : frames)
454  {
455  const std::vector<std::string> items = utils::split(frame, ':');
456  const std::string& str = items.front();
457 
458  const size_t tilde = str.find('~');
459  bool has_tilde = tilde != std::string::npos;
460  const std::string filename = "terrain/" + (has_tilde ? str.substr(0,tilde) : str);
461 
462  if(!image_exists(filename)){
463  continue; // ignore missing frames
464  }
465 
466  const std::string modif = (has_tilde ? str.substr(tilde+1) : "");
467 
468  int time = 100;
469  if(items.size() > 1) {
470  time = std::stoi(items.back());
471  }
472  image::locator locator;
473  if(ri.global_image) {
474  locator = image::locator(filename, constraint.loc, ri.center_x, ri.center_y, modif);
475  } else {
476  locator = image::locator(filename, modif);
477  }
478  res.add_frame(time, locator);
479  }
480  if(res.get_frames_count() == 0)
481  break; // no valid images, don't register it
482 
483  res.start_animation(0, true);
484  variant.images.push_back(res);
485  }
486  if(variant.images.empty())
487  return false; //no valid images, rule is invalid
488  }
489  }
490  }
491 
492  return true;
493 }
494 
496 {
497  static const struct { int ii; int ij; int ji; int jj; } rotations[6] =
498  { { 1, 0, 0, 1 }, { 1, 1, -1, 0 }, { 0, 1, -1, -1 },
499  { -1, 0, 0, -1 }, { -1, -1, 1, 0 }, { 0, -1, 1, 1 } };
500 
501  // The following array of matrices is intended to rotate the (x,y)
502  // coordinates of a point in a wesnoth hex (and wesnoth hexes are not
503  // regular hexes :) ).
504  // The base matrix for a 1-step rotation with the wesnoth tile shape
505  // is:
506  //
507  // r = s^-1 * t * s
508  //
509  // with s = [[ 1 0 ]
510  // [ 0 -sqrt(3)/2 ]]
511  //
512  // and t = [[ -1/2 sqrt(3)/2 ]
513  // [ -sqrt(3)/2 1/2 ]]
514  //
515  // With t being the rotation matrix (pi/3 rotation), and s a matrix
516  // that transforms the coordinates of the wesnoth hex to make them
517  // those of a regular hex.
518  //
519  // (demonstration left as an exercise for the reader)
520  //
521  // So we have
522  //
523  // r = [[ 1/2 -3/4 ]
524  // [ 1 1/2 ]]
525  //
526  // And the following array contains I(2), r, r^2, r^3, r^4, r^5
527  // (with r^3 == -I(2)), which are the successive rotations.
528  static const struct {
529  double xx;
530  double xy;
531  double yx;
532  double yy;
533  } xyrotations[6] = {
534  { 1., 0., 0., 1. },
535  { 1./2. , -3./4., 1., 1./2. },
536  { -1./2., -3./4., 1, -1./2.},
537  { -1. , 0., 0., -1. },
538  { -1./2., 3./4., -1., -1./2.},
539  { 1./2. , 3./4., -1., 1./2. },
540  };
541 
542  assert(angle >= 0);
543 
544  angle %= 6;
545 
546  // Vector i is going from n to s, vector j is going from ne to sw.
547  int vi = ret.loc.y - ret.loc.x/2;
548  int vj = ret.loc.x;
549 
550  int ri = rotations[angle].ii * vi + rotations[angle].ij * vj;
551  int rj = rotations[angle].ji * vi + rotations[angle].jj * vj;
552 
553  ret.loc.x = rj;
554  ret.loc.y = ri + (rj >= 0 ? rj/2 : (rj-1)/2);
555 
556  for (rule_imagelist::iterator itor = ret.images.begin();
557  itor != ret.images.end(); ++itor) {
558 
559  double vx, vy, rx, ry;
560 
561  vx = double(itor->basex) - double(tilewidth_)/2;
562  vy = double(itor->basey) - double(tilewidth_)/2;
563 
564  rx = xyrotations[angle].xx * vx + xyrotations[angle].xy * vy;
565  ry = xyrotations[angle].yx * vx + xyrotations[angle].yy * vy;
566 
567  itor->basex = int(rx + tilewidth_/2);
568  itor->basey = int(ry + tilewidth_/2);
569 
570  //std::cerr << "Rotation: from " << vx << ", " << vy << " to " << itor->basex <<
571  // ", " << itor->basey << "\n";
572  }
573 }
574 
576  const std::vector<std::string> &replacement)
577 {
578  std::string::size_type pos = 0;
579  while ((pos = s.find("@R", pos)) != std::string::npos) {
580  if (pos + 2 >= s.size()) return;
581  unsigned i = s[pos + 2] - '0' + angle;
582  if (i >= 6) i -= 6;
583  if (i >= 6) { pos += 2; continue; }
584  const std::string &r = replacement[i];
585  s.replace(pos, 3, r);
586  pos += r.size();
587  }
588 }
589 
591  const std::vector<std::string> &replacement)
592 {
593  for(rule_image_variant& variant : image.variants) {
594  replace_rotate_tokens(variant, angle, replacement);
595  }
596 }
597 
599  const std::vector<std::string> &replacement)
600 {
601  for(rule_image &img : list) {
602  replace_rotate_tokens(img, angle, replacement);
603  }
604 }
605 
607  const std::vector<std::string> &replacement)
608 {
609  for(terrain_constraint &cons : rule.constraints)
610  {
611  // Transforms attributes
612  for(std::string &flag : cons.set_flag) {
613  replace_rotate_tokens(flag, angle, replacement);
614  }
615  for(std::string &flag : cons.no_flag) {
616  replace_rotate_tokens(flag, angle, replacement);
617  }
618  for(std::string &flag : cons.has_flag) {
619  replace_rotate_tokens(flag, angle, replacement);
620  }
621  replace_rotate_tokens(cons.images, angle, replacement);
622  }
623 
624  //replace_rotate_tokens(rule.images, angle, replacement);
625 }
626 
628  const std::vector<std::string> &rot)
629 {
630  if (rot.size() != 6) {
631  ERR_NG << "invalid rotations" << std::endl;
632  return;
633  }
634 
635  for(terrain_constraint &cons : ret.constraints) {
636  rotate(cons, angle);
637  }
638 
639  // Normalize the rotation, so that it starts on a positive location
640  int minx = INT_MAX;
641  int miny = INT_MAX;
642 
643  for(const terrain_constraint &cons : ret.constraints) {
644  minx = std::min<int>(cons.loc.x, minx);
645  miny = std::min<int>(2 * cons.loc.y + (cons.loc.x & 1), miny);
646  }
647 
648  if((miny & 1) && (minx & 1) && (minx < 0))
649  miny += 2;
650  if(!(miny & 1) && (minx & 1) && (minx > 0))
651  miny -= 2;
652 
653  for(terrain_constraint &cons : ret.constraints) {
654  legacy_sum_assign(cons.loc,map_location(-minx, -((miny - 1) / 2)));
655  }
656 
657  replace_rotate_tokens(ret, angle, rot);
658 }
659 
660 terrain_builder::rule_image_variant::rule_image_variant(const std::string &image_string, const std::string& variations, const std::string& tod, const std::string& has_flag, bool random_start) :
661  image_string(image_string),
662  variations(variations),
663  images(),
664  tods(),
665  has_flag(),
666  random_start(random_start)
667 {
668  if(!has_flag.empty()) {
669  this->has_flag = utils::split(has_flag);
670  }
671  if(!tod.empty()) {
672  const std::vector<std::string> tod_list = utils::split(tod);
673  tods.insert(tod_list.begin(), tod_list.end());
674  }
675 }
676 
677 void terrain_builder::add_images_from_config(rule_imagelist& images, const config &cfg, bool global, int dx, int dy)
678 {
679  for (const config &img : cfg.child_range("image"))
680  {
681  int layer = img["layer"];
682 
683  int basex = tilewidth_ / 2 + dx, basey = tilewidth_ / 2 + dy;
684  if (const config::attribute_value *base_ = img.get("base")) {
685  std::vector<std::string> base = utils::split(*base_);
686  if(base.size() >= 2) {
687  basex = std::stoi(base[0]);
688  basey = std::stoi(base[1]);
689  }
690  }
691 
692  int center_x = -1, center_y = -1;
693  if (const config::attribute_value *center_ = img.get("center")) {
694  std::vector<std::string> center = utils::split(*center_);
695  if(center.size() >= 2) {
696  center_x = std::stoi(center[0]);
697  center_y = std::stoi(center[1]);
698  }
699  }
700 
701  bool is_water = img["is_water"].to_bool();
702 
703  images.push_back(rule_image(layer, basex - dx, basey - dy, global, center_x, center_y, is_water));
704 
705  // Adds the other variants of the image
706  for(const config &variant : img.child_range("variant"))
707  {
708  const std::string &name = variant["name"];
709  const std::string &variations = img["variations"];
710  const std::string &tod = variant["tod"];
711  const std::string &has_flag = variant["has_flag"];
712  bool random_start = variant["random_start"].to_bool(true);
713 
714  images.back().variants.push_back(rule_image_variant(name, variations, tod, has_flag, random_start));
715  }
716 
717  // Adds the main (default) variant of the image at the end,
718  // (will be used only if previous variants don't match)
719  const std::string &name = img["name"];
720  const std::string &variations = img["variations"];
721  bool random_start = img["random_start"].to_bool(true);
722  images.back().variants.push_back(rule_image_variant(name, variations, random_start));
723  }
724 }
725 
727  terrain_builder::constraint_set& constraints,
728  const map_location& loc,
729  const t_translation::t_match& type, const config& global_images)
730 {
731  terrain_constraint *cons = nullptr;
732  for (terrain_constraint &c : constraints) {
733  if (c.loc == loc) {
734  cons = &c;
735  break;
736  }
737  }
738 
739  if (!cons) {
740  // The terrain at the current location did not exist, so create it
741  constraints.push_back(terrain_constraint(loc));
742  cons = &constraints.back();
743  }
744 
745  if(!type.terrain.empty()) {
746  cons->terrain_types_match = type;
747  }
748 
749  int x = loc.x * tilewidth_ * 3 / 4;
750  int y = loc.y * tilewidth_ + (loc.x % 2) * tilewidth_ / 2;
751  add_images_from_config(cons->images, global_images, true, x, y);
752 
753  return *cons;
754 }
755 
757  const map_location& loc, const config& cfg, const config& global_images)
758 
759 {
760  terrain_constraint& constraint = add_constraints(constraints, loc,
761  t_translation::t_match(cfg["type"], t_translation::WILDCARD), global_images);
762 
763 
764  std::vector<std::string> item_string = utils::square_parenthetical_split(cfg["set_flag"],',',"[","]");
765  constraint.set_flag.insert(constraint.set_flag.end(),
766  item_string.begin(), item_string.end());
767 
768  item_string = utils::square_parenthetical_split(cfg["has_flag"],',',"[","]");
769  constraint.has_flag.insert(constraint.has_flag.end(),
770  item_string.begin(), item_string.end());
771 
772  item_string = utils::square_parenthetical_split(cfg["no_flag"],',',"[","]");
773  constraint.no_flag.insert(constraint.no_flag.end(),
774  item_string.begin(), item_string.end());
775 
776  item_string = utils::square_parenthetical_split(cfg["set_no_flag"],',',"[","]");
777  constraint.set_flag.insert(constraint.set_flag.end(),
778  item_string.begin(), item_string.end());
779  constraint.no_flag.insert(constraint.no_flag.end(),
780  item_string.begin(), item_string.end());
781 
782 
783  constraint.no_draw = cfg["no_draw"].to_bool(false);
784 
785  add_images_from_config(constraint.images, cfg, false);
786 }
787 
789  struct building_rule &br, anchormap& anchors,
790  const config& global_images)
791 {
792 
794 
795  // If there is an empty map leave directly.
796  // Determine after conversion, since a
797  // non-empty string can return an empty map.
798  if(map.empty()) {
799  return;
800  }
801 
802  int lineno = (map[0][0] == t_translation::NONE_TERRAIN) ? 1 : 0;
803  int x = lineno;
804  int y = 0;
805  for(size_t y_off = 0; y_off < map.size(); ++y_off) {
806  for(size_t x_off = x; x_off < map[y_off].size(); ++x_off) {
807 
808  const t_translation::t_terrain terrain = map[y_off][x_off];
809 
810  if(terrain.base == t_translation::TB_DOT) {
811  // Dots are simple placeholders,
812  // which do not represent actual terrains.
813  } else if (terrain.overlay != 0 ) {
814  anchors.insert(std::pair<int, map_location>(terrain.overlay, map_location(x, y)));
815  } else if (terrain.base == t_translation::TB_STAR) {
816  add_constraints(br.constraints, map_location(x, y), t_translation::STAR, global_images);
817  } else {
818  ERR_NG << "Invalid terrain (" << t_translation::write_terrain_code(terrain) << ") in builder map" << std::endl;
819  assert(false);
820  return;
821  }
822  x += 2;
823  }
824 
825  if(lineno % 2 == 1) {
826  ++y;
827  x = 0;
828  } else {
829  x = 1;
830  }
831  ++lineno;
832  }
833 }
834 
836 {
837  if(load_images(rule)) {
838  rules.insert(rule);
839  }
840 }
841 
843  const std::string &rotations)
844 {
845  if(rotations.empty()) {
846  // Adds the parsed built terrain to the list
847 
848  add_rule(rules, tpl);
849  } else {
850  const std::vector<std::string>& rot = utils::split(rotations, ',');
851 
852  for(size_t angle = 0; angle < rot.size(); ++angle) {
853  /* Only 5% of the rules have valid images, so most of
854  them will be discarded. If the ratio was higher,
855  it would be more efficient to insert a copy of the
856  template rule into the ruleset, modify it in place,
857  and remove it if invalid. But since the ratio is so
858  low, the speedup is not worth the extra multiset
859  manipulations. */
860  building_rule rule = tpl;
861  rotate_rule(rule, angle, rot);
862  add_rule(rules, rule);
863  }
864  }
865 }
866 
867 void terrain_builder::parse_config(const config &cfg, bool local)
868 {
869  log_scope("terrain_builder::parse_config");
870  int n = 0;
871 
872  // Parses the list of building rules (BRs)
873  for(const config &br : cfg.child_range("terrain_graphics"))
874  {
875  building_rule pbr; // Parsed Building rule
876  pbr.local = local;
877 
878  // add_images_from_config(pbr.images, **br);
879 
881  map_location(br["x"].to_int() - 1, br["y"].to_int() - 1);
882 
883  pbr.modulo_constraints =
884  map_location(br["mod_x"].to_int(), br["mod_y"].to_int());
885 
886  pbr.probability = br["probability"].to_int(100);
887 
888  // Mapping anchor indices to anchor locations.
889  anchormap anchors;
890 
891  // Parse the map= , if there is one (and fill the anchors list)
892  parse_mapstring(br["map"], pbr, anchors, br);
893 
894  // Parses the terrain constraints (TCs)
895  for (const config &tc : br.child_range("tile"))
896  {
897  // Adds the terrain constraint to the current built terrain's list
898  // of terrain constraints, if it does not exist.
899  map_location loc;
900  if (const config::attribute_value *v = tc.get("x")) {
901  loc.x = *v;
902  }
903  if (const config::attribute_value *v = tc.get("y")) {
904  loc.y = *v;
905  }
906  if(loc.valid()) {
907  add_constraints(pbr.constraints, loc, tc, br);
908  }
909  if (const config::attribute_value *v = tc.get("pos")) {
910  int pos = *v;
911  if(anchors.find(pos) == anchors.end()) {
912  WRN_NG << "Invalid anchor!" << std::endl;
913  continue;
914  }
915 
916  std::pair<anchormap::const_iterator, anchormap::const_iterator> range =
917  anchors.equal_range(pos);
918 
919  for(; range.first != range.second; ++range.first) {
920  loc = range.first->second;
921  add_constraints(pbr.constraints, loc, tc, br);
922  }
923  }
924  }
925 
926  const std::vector<std::string> global_set_flag = utils::split(br["set_flag"]);
927  const std::vector<std::string> global_no_flag = utils::split(br["no_flag"]);
928  const std::vector<std::string> global_has_flag = utils::split(br["has_flag"]);
929  const std::vector<std::string> global_set_no_flag = utils::split(br["set_no_flag"]);
930 
931  for(terrain_constraint &constraint : pbr.constraints)
932  {
933  constraint.set_flag.insert(constraint.set_flag.end(),
934  global_set_flag.begin(), global_set_flag.end());
935  constraint.no_flag.insert(constraint.no_flag.end(),
936  global_no_flag.begin(), global_no_flag.end());
937  constraint.has_flag.insert(constraint.has_flag.end(),
938  global_has_flag.begin(), global_has_flag.end());
939  constraint.set_flag.insert(constraint.set_flag.end(),
940  global_set_no_flag.begin(), global_set_no_flag.end());
941  constraint.no_flag.insert(constraint.no_flag.end(),
942  global_set_no_flag.begin(), global_set_no_flag.end());
943  }
944 
945  // Handles rotations
946  const std::string &rotations = br["rotations"];
947 
948  pbr.precedence = br["precedence"];
949 
950  add_rotated_rules(building_rules_, pbr, rotations);
951 
952  n++;
953  if(n % 10 == 0) {
955  }
956  }
957 
958 // Debug output for the terrain rules
959 #if 0
960  std::cerr << "Built terrain rules: \n";
961 
962  building_ruleset::const_iterator rule;
963  for(rule = building_rules_.begin(); rule != building_rules_.end(); ++rule) {
964  std::cerr << ">> New rule: image_background = "
965  << "\n>> Location " << rule->second.location_constraints
966  << "\n>> Probability " << rule->second.probability
967 
968  for(constraint_set::const_iterator constraint = rule->second.constraints.begin();
969  constraint != rule->second.constraints.end(); ++constraint) {
970 
971  std::cerr << ">>>> New constraint: location = (" << constraint->second.loc
972  << "), terrain types = '" << t_translation::write_list(constraint->second.terrain_types_match.terrain) << "'\n";
973 
974  std::vector<std::string>::const_iterator flag;
975 
976  for(flag = constraint->second.set_flag.begin(); flag != constraint->second.set_flag.end(); ++flag) {
977  std::cerr << ">>>>>> Set_flag: " << *flag << "\n";
978  }
979 
980  for(flag = constraint->second.no_flag.begin(); flag != constraint->second.no_flag.end(); ++flag) {
981  std::cerr << ">>>>>> No_flag: " << *flag << "\n";
982  }
983  }
984 
985  }
986 #endif
987 
988 }
989 
991 {
992  // Build a config object
993  config cfg;
994 
995  config &item = cfg.add_child("terrain_graphics");
996 
997  config &tile = item.add_child("tile");
998  tile["x"] = 0;
999  tile["y"] = 0;
1001 
1002  config &tile_image = tile.add_child("image");
1003  tile_image["layer"] = -1000;
1004  tile_image["name"] = image;
1005 
1006  item["probability"] = 100;
1007  item["no_flag"] = "base";
1008  item["set_flag"] = "base";
1009 
1010  // Parse the object
1011  parse_global_config(cfg);
1012 }
1013 
1015  const map_location &loc, const terrain_constraint *type_checked) const
1016 {
1017  // Don't match if the location isn't a multiple of mod_x and mod_y
1018  if(rule.modulo_constraints.x > 0 && (loc.x % rule.modulo_constraints.x != 0)) {
1019  return false;
1020  }
1021  if(rule.modulo_constraints.y > 0 && (loc.y % rule.modulo_constraints.y != 0)) {
1022  return false;
1023  }
1024 
1025  if(rule.location_constraints.valid() && rule.location_constraints != loc) {
1026  return false;
1027  }
1028 
1029  if(rule.probability != 100) {
1030  unsigned int random = get_noise(loc, rule.get_hash()) % 100;
1031  if(random > static_cast<unsigned int>(rule.probability)) {
1032  return false;
1033  }
1034  }
1035 
1036  for(const terrain_constraint &cons : rule.constraints)
1037  {
1038  // Translated location
1039  const map_location tloc = legacy_sum(loc,cons.loc);
1040 
1041  if(!tile_map_.on_map(tloc)) {
1042  return false;
1043  }
1044 
1045  //std::cout << "testing..." << builder_letter(map().get_terrain(tloc))
1046 
1047  // check if terrain matches except if we already know that it does
1048  if (&cons != type_checked && !terrain_matches(map().get_terrain(tloc), cons.terrain_types_match)) {
1049  return false;
1050  }
1051 
1052  const std::set<std::string> &flags = tile_map_[tloc].flags;
1053 
1054  for (const std::string &s : cons.no_flag) {
1055  // If a flag listed in "no_flag" is present, the rule does not match
1056  if (flags.find(s) != flags.end()) {
1057  return false;
1058  }
1059  }
1060  for (const std::string &s : cons.has_flag) {
1061  // If a flag listed in "has_flag" is not present, this rule does not match
1062  if (flags.find(s) == flags.end()) {
1063  return false;
1064  }
1065  }
1066  }
1067 
1068  return true;
1069 }
1070 
1072 {
1073  unsigned int rand_seed = get_noise(loc, rule.get_hash());
1074 
1075  for(const terrain_constraint &constraint : rule.constraints)
1076  {
1077  const map_location tloc = legacy_sum(loc,constraint.loc);
1078  if(!tile_map_.on_map(tloc)) {
1079  return;
1080  }
1081 
1082  tile& btile = tile_map_[tloc];
1083 
1084  if (!constraint.no_draw) {
1085  for (const rule_image &img : constraint.images) {
1086  btile.images.push_back(tile::rule_image_rand(&img, rand_seed));
1087  }
1088  }
1089 
1090  // Sets flags
1091  for (const std::string &flag : constraint.set_flag) {
1092  btile.flags.insert(flag);
1093  }
1094 
1095  }
1096 }
1097 
1098 // copied from text_surface::hash()
1099 // but keep it separated because the needs are different
1100 // and changing it will modify the map random variations
1101 static unsigned int hash_str(const std::string& str)
1102 {
1103  unsigned int h = 0;
1104  for(std::string::const_iterator it = str.begin(), it_end = str.end(); it != it_end; ++it)
1105  h = ((h << 9) | (h >> (sizeof(int) * 8 - 9))) ^ (*it);
1106  return h;
1107 }
1108 
1110 {
1111  if(hash_ != DUMMY_HASH)
1112  return hash_;
1113 
1114  for(const terrain_constraint &constraint : constraints) {
1115  for(const rule_image& ri : constraint.images) {
1116  for(const rule_image_variant& variant : ri.variants) {
1117  // we will often hash the same string, but that seems fast enough
1118  hash_ += hash_str(variant.image_string);
1119  }
1120  }
1121  }
1122 
1123  //don't use the reserved dummy hash
1124  if(hash_ == DUMMY_HASH)
1125  hash_ = 105533; // just a random big prime number
1126 
1127  return hash_;
1128 }
1129 
1131 {
1132  log_scope("terrain_builder::build_terrains");
1133 
1134  // Builds the terrain_by_type_ cache
1135  for(int x = -2; x <= map().w(); ++x) {
1136  for(int y = -2; y <= map().h(); ++y) {
1137  const map_location loc(x,y);
1138  const t_translation::t_terrain t = map().get_terrain(loc);
1139 
1140  terrain_by_type_[t].push_back(loc);
1141  }
1142  }
1143 
1144  for(const building_rule &rule : building_rules_)
1145  {
1146  // Find the constraint that contains the less terrain of all terrain rules.
1147  // We will keep a track of the matching terrains of this constraint
1148  // and later try to apply the rule only on them
1149  size_t min_size = INT_MAX;
1150  t_translation::t_list min_types = t_translation::t_list(); // <-- This must be explicitly initialized, just as min_constraint is, at start of loop, or we get a null pointer dereference when we go through on later times.
1151  const terrain_constraint *min_constraint = nullptr;
1152 
1153  for(const terrain_constraint &constraint : rule.constraints)
1154  {
1155  const t_translation::t_match& match = constraint.terrain_types_match;
1156  t_translation::t_list matching_types;
1157  size_t constraint_size = 0;
1158 
1159  for (terrain_by_type_map::iterator type_it = terrain_by_type_.begin();
1160  type_it != terrain_by_type_.end(); ++type_it) {
1161 
1162  const t_translation::t_terrain t = type_it->first;
1163  if (terrain_matches(t, match)) {
1164  const size_t match_size = type_it->second.size();
1165  constraint_size += match_size;
1166  if (constraint_size >= min_size) {
1167  break; // not a minimum, bail out
1168  }
1169  matching_types.push_back(t);
1170  }
1171  }
1172 
1173  if (constraint_size < min_size) {
1174  min_size = constraint_size;
1175  min_types = matching_types;
1176  min_constraint = &constraint;
1177  if (min_size == 0) {
1178  // a constraint is never matched on this map
1179  // we break with a empty type list
1180  break;
1181  }
1182  }
1183  }
1184 
1185  //NOTE: if min_types is not empty, we have found a valid min_constraint;
1186  for(t_translation::t_list::const_iterator t = min_types.begin();
1187  t != min_types.end(); ++t) {
1188 
1189  const std::vector<map_location>* locations = &terrain_by_type_[*t];
1190 
1191  for(std::vector<map_location>::const_iterator itor = locations->begin();
1192  itor != locations->end(); ++itor) {
1193  const map_location loc = legacy_difference(*itor,min_constraint->loc);
1194 
1195  if(rule_matches(rule, loc, min_constraint)) {
1196  apply_rule(rule, loc);
1197  }
1198  }
1199  }
1200 
1201  }
1202 }
1203 
1205 {
1206  if(tile_map_.on_map(loc))
1207  return &(tile_map_[loc]);
1208  return nullptr;
1209 }
void rebuild_terrain(const map_location &loc)
Performs a "quick-rebuild" of the terrain in a given location.
Definition: builder.cpp:353
void reload_map()
Updates internals that cache map size.
Definition: builder.cpp:293
child_itors child_range(const std::string &key)
Definition: config.cpp:613
tformula< unsigned > x_
The x coordinate of the rectangle.
Definition: canvas.cpp:682
const t_terrain STAR
const t_layer TB_DOT
The in-memory representation of a [terrain_graphics] WML rule.
Definition: builder.hpp:368
void precache_file_existence(const std::string &subdir)
precache the existence of files in the subdir (ex: "terrain/")
Definition: image.cpp:1229
terrain_by_type_map terrain_by_type_
A map representing all locations whose terrain is of a given type.
Definition: builder.hpp:810
tile * get_tile(const map_location &loc)
Definition: builder.cpp:1204
terrain_constraint & add_constraints(constraint_set &constraints, const map_location &loc, const t_translation::t_match &type, const config &global_images)
Creates a rule constraint object which matches a given list of terrains, and adds it to the list of c...
Definition: builder.cpp:726
map_location modulo_constraints
Used to constrain locations to ones with coordinates that are multiples of the "mod_x" and "mod_y" pa...
Definition: builder.hpp:397
void reset()
Resets the whole tile map.
Definition: builder.cpp:199
GLint level
Definition: glew.h:1220
The in-memory representation of a [tile] WML rule inside of a [terrain_graphics] WML rule...
Definition: builder.hpp:251
void add_rule(building_ruleset &rules, building_rule &rule)
Adds a rule to a ruleset.
Definition: builder.cpp:835
GLenum GLint * range
Definition: glew.h:3025
const GLfloat * c
Definition: glew.h:12741
int pos
Definition: formula.cpp:800
rule_image_variant(const std::string &image_string, const std::string &variations, bool random_start=true)
Constructor for the normal defaut case.
Definition: builder.hpp:155
tile & operator[](const map_location &loc)
Returns a reference to the tile which is at the position pointed by loc.
Definition: builder.cpp:224
bool no_draw
Whether to actually draw the images onto this hex or not.
Definition: builder.hpp:280
const t_layer WILDCARD
Definition: translation.hpp:37
bool precached_file_exists(const std::string &file)
Definition: image.cpp:1240
void add_off_map_rule(const std::string &image)
Adds a builder rule for the _off^_usr tile, this tile only has 1 image.
Definition: builder.cpp:990
GLuint GLuint GLsizei GLenum type
Definition: glew.h:1221
const t_terrain NONE_TERRAIN
Definition: translation.hpp:56
const std::string & minimap_image_overlay() const
Definition: terrain.hpp:31
bool load_images(building_rule &rule)
Load images and tests for validity of a rule.
Definition: builder.cpp:431
std::vector< terrain_constraint > constraint_set
The list of constraints attached to a terrain_graphics WML rule.
Definition: builder.hpp:363
Represent a rule_image applied with a random seed.
Definition: builder.hpp:314
imagelist images_background
The list of images which are behind the unit sprites, attached to this tile.
Definition: builder.hpp:340
int precedence
Ordering relation between the rules.
Definition: builder.hpp:409
static building_ruleset building_rules_
Parsed terrain rules.
Definition: builder.hpp:813
std::multimap< int, map_location > anchormap
Definition: builder.hpp:677
void rebuild_cache_all()
Definition: builder.cpp:264
GLenum GLsizei GLenum GLenum const GLvoid * image
Definition: glew.h:3783
t_translation::t_match terrain_types_match
Definition: builder.hpp:274
const formula_callable & base_
Definition: formula.cpp:568
void add_frame(int duration, const T &value, bool force_change=false)
Adds a frame to an animation.
const int tilewidth_
The tile width used when using basex and basey.
Definition: builder.hpp:358
#define h
static map_location & legacy_sum_assign(map_location &me, const map_location &a)
Definition: builder.cpp:56
GLint GLint GLint GLint GLint GLint y
Definition: glew.h:1220
const std::vector< std::string > items
bool animate_water()
static map_location legacy_difference(const map_location &me, const map_location &a)
Definition: builder.cpp:76
static lg::log_domain log_engine("engine")
size_t get_frames_count() const
GLdouble GLdouble t
Definition: glew.h:1366
bool rule_matches(const building_rule &rule, const map_location &loc, const terrain_constraint *type_checked) const
Checks whether a rule matches a given location in the map.
Definition: builder.cpp:1014
const t_terrain OFF_MAP_USER
void add_rotated_rules(building_ruleset &rules, building_rule &tpl, const std::string &rotations)
Adds a set of rules to a ruleset, from a template rule which spans 6 rotations (or less if some of th...
Definition: builder.cpp:842
Variant for storing WML attributes.
Definition: config.hpp:223
void apply_rule(const building_rule &rule, const map_location &loc)
Applies a rule at a given location: applies the result of a matching rule at a given location: attach...
Definition: builder.cpp:1071
static unsigned int get_noise(const map_location &loc, unsigned int index)
Definition: builder.cpp:191
#define WRN_NG
Definition: builder.cpp:31
void rebuild_all()
Performs a complete rebuild of the list of terrain graphics attached to a map.
Definition: builder.cpp:385
static const unsigned int DUMMY_HASH
Definition: builder.hpp:65
void rebuild_cache(const std::string &tod, logs *log=nullptr)
Rebuilds the whole image cache, for a given time-of-day.
Definition: builder.cpp:110
void replace_rotate_tokens(std::string &s, int angle, const std::vector< std::string > &replacement)
Replaces, in a given string, rotation tokens with their values.
Definition: builder.cpp:575
int probability
The probability of this rule to match, when all conditions are met.
Definition: builder.hpp:404
Represents a tile of the game map, with all associated builder-specific parameters: flags...
Definition: builder.hpp:291
void change_map(const gamemap *m)
Definition: builder.cpp:300
GLdouble GLdouble GLdouble b
Definition: glew.h:6966
std::vector< std::vector< t_terrain > > t_map
Definition: translation.hpp:76
bool exists(const image::locator &i_locator)
returns true if the given image actually exists, without loading it.
Definition: image.cpp:1187
int hash_
Definition: font.cpp:603
void update_last_draw_time(double acceleration=0)
const gamemap * map_
A pointer to the gamemap class used in the current level.
Definition: builder.hpp:793
std::string write_list(const t_list &list)
Writes a list of terrains to a string, only writes the new format.
GLenum GLenum GLuint GLint GLint layer
Definition: glew.h:3455
bool valid() const
Definition: location.hpp:69
This structure can be used for matching terrain strings.
Definition: translation.hpp:83
GLubyte GLubyte GLubyte GLubyte w
Definition: glew.h:1858
const GLdouble * v
Definition: glew.h:1359
int w() const
Effective map width.
Definition: map.hpp:105
tilemap tile_map_
The tile_map_ for the current level, which is filled by the build_terrains_ method to contain "tiles"...
Definition: builder.hpp:800
static bool image_exists(const std::string &name)
Definition: builder.cpp:392
GLboolean GLboolean GLboolean GLboolean a
Definition: glew.h:7319
#define ERR_NG
Definition: builder.cpp:30
Encapsulates the map of the game.
Definition: map.hpp:37
std::set< std::string > tods
The Time of Day associated to this variant (if any)
Definition: builder.hpp:198
TERRAIN_TYPE
Used as a parameter for the get_terrain_at function.
Definition: builder.hpp:47
config & add_child(const std::string &key)
Definition: config.cpp:743
void flush_local_rules()
Definition: builder.cpp:273
terrain_builder(const config &level, const gamemap *map, const std::string &offmap_image)
Constructor for the terrain_builder class.
Definition: builder.cpp:238
std::vector< rule_image_variant > variants
A list of variants for this image.
Definition: builder.hpp:228
bool need_update() const
const T & get_frame(size_t n) const
std::vector< rule_image_rand > images
The list of rule_images and random seeds associated to this tile.
Definition: builder.hpp:329
static const ::config * terrain
The terrain used to create the cache.
Definition: minimap.cpp:135
typedef int(WINAPI *PFNWGLRELEASEPBUFFERDCARBPROC)(HPBUFFERARB hPbuffer
const t_layer TB_STAR
std::vector< log_details > logs
Definition: builder.hpp:298
GLsizei const GLint * locations
Definition: glew.h:11075
std::vector< animated< image::locator > > images
An animated image locator built according to the image string.
Definition: builder.hpp:195
cl_event GLbitfield flags
Definition: glew.h:3070
bool local
Indicate if the rule is only for this scenario.
Definition: builder.hpp:414
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
Definition: translation.hpp:47
GLboolean reset
Definition: glew.h:3799
Encapsulates the map of the game.
Definition: location.hpp:38
const terrain_type & get_terrain_info(const t_translation::t_terrain &terrain) const
Definition: map.cpp:100
void rotate_rule(building_rule &rule, int angle, const std::vector< std::string > &angle_name)
Rotates a template rule to a given angle.
Definition: builder.cpp:627
bool update_animation(const map_location &loc)
Updates the animation at a given tile.
Definition: builder.cpp:329
GLuint res
Definition: glew.h:9258
static void progress(const char *stage_name=nullptr)
Definition: loadscreen.cpp:128
bool global_image
Set to true if the image was defined as a child of the [terrain_graphics] tag, set to false if it was...
Definition: builder.hpp:233
std::map< std::string, tfilter >::iterator itor
Definition: filter.cpp:199
std::string last_tod
The time-of-day to which the image caches correspond.
Definition: builder.hpp:344
void rotate(terrain_constraint &constraint, int angle)
"Rotates" a constraint from a rule.
Definition: builder.cpp:495
int h() const
Effective map height.
Definition: map.hpp:108
static const config * rules_cfg_
Config used to parse global terrain rules.
Definition: builder.hpp:816
std::vector< std::string > set_flag
Definition: builder.hpp:275
Game configuration data as global variables.
Definition: build_info.cpp:38
GLuint index
Definition: glew.h:1782
std::set< std::string > flags
The list of flags present in this tile.
Definition: builder.hpp:311
unsigned int get_hash() const
Definition: builder.cpp:1109
rule_image(int layer, int x, int y, bool global_image=false, int center_x=-1, int center_y=-1, bool is_water=false)
Definition: builder.cpp:90
std::vector< rule_image > rule_imagelist
A shorthand notation for a vector of rule_images.
Definition: builder.hpp:245
#define log_scope(description)
Definition: log.hpp:185
GLfloat GLfloat GLfloat GLfloat h
Definition: glew.h:5910
size_t i
Definition: function.cpp:1057
GLint GLint GLint GLint GLint x
Definition: glew.h:1220
void parse_mapstring(const std::string &mapstring, struct building_rule &br, anchormap &anchors, const config &global_images)
Parses a map string (the map= element of a [terrain_graphics] rule, and adds constraints from this ma...
Definition: builder.cpp:788
tformula< unsigned > y_
The y coordinate of the rectangle.
Definition: canvas.cpp:682
std::vector< std::string > has_flag
Definition: builder.hpp:200
GLdouble GLdouble GLdouble r
Definition: glew.h:1374
Definitions for the terrain builder.
int center_x
The position where the center of the image base should be.
Definition: builder.hpp:237
void reload(int x, int y)
Rebuilds the map to a new set of dimensions.
Definition: builder.cpp:205
Represents terrains which are to be drawn behind unit sprites.
Definition: builder.hpp:48
Each terrain_graphics rule is associated a set of images, which are applied on the terrain if the rul...
Definition: builder.hpp:213
std::vector< std::string > has_flag
Definition: builder.hpp:277
std::string write_terrain_code(const t_terrain &tcode)
Writes a single terrain code to a string.
static map_location legacy_negation(const map_location &me)
These legacy map_location functions moved here from map_location.
Definition: builder.cpp:51
std::vector< animated< image::locator > > imagelist
A shorthand typedef for a list of animated image locators, the base data type returned by the get_ter...
Definition: builder.hpp:70
const GLfloat * tc
Definition: glew.h:12749
GLuint const GLchar * name
Definition: glew.h:1782
void build_terrains()
Calculates the list of terrains, and fills the tile_map_ member, from the gamemap and the building_ru...
Definition: builder.cpp:1130
t_translation::t_terrain get_terrain(const map_location &loc) const
Looks up terrain at a particular location.
Definition: map.cpp:341
tile()
Constructor for the tile() structure.
Definition: builder.cpp:101
std::multiset< building_rule > building_ruleset
A set of building rules.
Definition: builder.hpp:485
constraint_set constraints
The set of [tile] constraints of this rule.
Definition: builder.hpp:383
static std::map< std::string, std::string > images
Definition: about.cpp:58
GLclampd n
Definition: glew.h:5903
static void set_terrain_rules_cfg(const config &cfg)
Set the config where we will parse the global terrain rules.
Definition: builder.cpp:284
bool random_start
Indicate if the animation uses a random shift.
Definition: builder.hpp:203
const GLdouble * m
Definition: glew.h:6968
void add_images_from_config(rule_imagelist &images, const config &cfg, bool global, int dx=0, int dy=0)
Parses a "config" object, which should contains [image] children, and adds the corresponding parsed r...
Definition: builder.cpp:677
bool is_empty_hex(const locator &i_locator)
function to check if an image is empty after hex cut should be only used on terrain image (cache the ...
Definition: image.cpp:1146
map_location location_constraints
The location on which this map may match.
Definition: builder.hpp:390
void swap(game_board &one, game_board &other)
Definition: game_board.cpp:56
GLint GLvoid * img
Definition: glew.h:1353
bool terrain_matches(const t_translation::t_terrain &tcode, const t_translation::t_list &terrains) const
Checks whether a terrain code matches a given list of terrain codes.
Definition: builder.hpp:747
GLdouble angle
Definition: glew.h:6979
this module manages the cache of images.
Definition: image.cpp:75
Standard logging facilities (interface).
static const char * match(MatchState *ms, const char *s, const char *p)
Definition: lstrlib.cpp:409
#define c
Definition: glew.h:12743
std::string image_string
A string representing either the filename for an image, or a list of images, with an optional timing ...
Definition: builder.hpp:184
std::string variations
A semi-solon separated list of string used to replace.
Definition: builder.hpp:189
std::vector< std::string > split(std::string const &val, const char c, const int flags)
Splits a (comma-)separated string into a vector of pieces.
void parse_config(const config &cfg, bool local=true)
Parses a configuration object containing [terrain_graphics] rules, and fills the building_rules_ memb...
Definition: builder.cpp:867
static unsigned int hash_str(const std::string &str)
Definition: builder.cpp:1101
static map_location legacy_sum(const map_location &me, const map_location &a)
Definition: builder.cpp:69
imagelist images_foreground
The list of images which are in front of the unit sprites, attached to this tile. ...
Definition: builder.hpp:335
std::string::const_iterator iterator
Definition: tokenizer.hpp:21
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:83
void parse_global_config(const config &cfg)
Definition: builder.hpp:724
void clear()
Clears all data in this tile, and resets the cache.
Definition: builder.cpp:181
GLdouble s
Definition: glew.h:1358
static std::vector< std::string > get_variations(const std::string &base, const std::string &variations)
Definition: builder.cpp:405
std::vector< std::string > square_parenthetical_split(std::string const &val, const char separator, std::string const &left, std::string const &right, const int flags)
Similar to parenthetical_split, but also expands embedded square brackets.
const std::string & minimap_image() const
Definition: terrain.hpp:30
std::vector< std::string > no_flag
Definition: builder.hpp:276
GLsizei const GLcharARB ** string
Definition: glew.h:4503
t_map read_builder_map(const std::string &str)
Reads a builder map.
bool on_map(const map_location &loc) const
Tests if a location is on the map.
Definition: builder.cpp:214
const gamemap & map() const
Definition: builder.hpp:94
std::vector< t_terrain > t_list
Definition: translation.hpp:75
void start_animation(int start_time, bool cycles=false)
Starts an animation cycle.
const imagelist * get_terrain_at(const map_location &loc, const std::string &tod, TERRAIN_TYPE const terrain_type)
Returns a vector of strings representing the images to load & blit together to get the built content ...
Definition: builder.cpp:306