widelands-dev team mailing list archive
-
widelands-dev team
-
Mailing list archive
-
Message #01100
[Merge] lp:~widelands-dev/widelands/clang_format into lp:widelands
SirVer has proposed merging lp:~widelands-dev/widelands/clang_format into lp:widelands.
Requested reviews:
Widelands Developers (widelands-dev)
For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/clang_format/+merge/164570
I just pushed up a branch for merge into trunk that contains significant changes to how style in Widelands works:
• It removes a very old style checker written in ada which did not run in years
• it fixes some smaller stuff (const and passing by reference mostly)
• it removes and alters some of the style rules the current style checker uses.
• it introduces a configuration file for clang-format (http://clang.llvm.org/docs/ClangFormat.html).
I posted also to widelands-public which is still the place to discuss these things I feel. I also encourage people seeing it here to join the discussion on the mailing list (feel free to drop comments here as well).
--
The attached diff has been truncated due to its size.
https://code.launchpad.net/~widelands-dev/widelands/clang_format/+merge/164570
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/clang_format into lp:widelands.
=== added file '.clang-format'
--- .clang-format 1970-01-01 00:00:00 +0000
+++ .clang-format 2013-05-18 05:56:27 +0000
@@ -0,0 +1,22 @@
+# Widelands style file for clang-format:
+# http://clang.llvm.org/docs/ClangFormat.html
+AccessModifierOffset: -2
+AlignEscapedNewlinesLeft: false
+AllowAllParametersOfDeclarationOnNextLine: false
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+BinPackParameters: false
+ColumnLimit: 100
+ConstructorInitializerAllOnOneLineOrOnePerLine: true
+DerivePointerBinding: false
+IndentCaseLabels: true
+MaxEmptyLinesToKeep: 1
+ObjCSpaceBeforeProtocolList: true
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 75
+PointerBindsToType: true
+SpacesBeforeTrailingComments: 2
+Standard: C++03
+IndentWidth: 3
+UseTab: false
+BreakBeforeBraces: Attach
=== modified file 'cmake/codecheck/rules/const_std_string_by_value'
--- cmake/codecheck/rules/const_std_string_by_value 2010-02-05 01:13:20 +0000
+++ cmake/codecheck/rules/const_std_string_by_value 2013-05-18 05:56:27 +0000
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python
"""
This catches std::string constants that are passed by value. They should be
@@ -7,7 +7,37 @@
error_msg="const std::string must not be passed by value. Pass by reference!"
-regexp=r"""[\( ](?:const +std::string|std::string +const)(?: +[_a-zA-Z][_a-zA-Z0-9]*)?(?: *=.*)?(?:,(?: |$)|\))"""
+regexp=r"""[\(](?:const +std::string|std::string +const)(?: +[_a-zA-Z][_a-zA-Z0-9]*)?(?: *=.*)?(?:,(?: |$)|\))"""
+
+import re
+
+_match_re1 = re.compile(r'const\s+string(\s+[_a-zA-Z][_a-zA-Z0-9]*)?(?!\s*&)')
+_match_re2 = re.compile(r'string\s+const(\s+[_a-zA-Z][_a-zA-Z0-9]*)?(?!\s*&)')
+
+def evaluate_matches(lines, fn):
+ errors = []
+
+ for lineno,line in enumerate(lines):
+ line = line.strip()
+ line = line.replace("std::", "")
+
+ if not (
+ line.startswith("(") or
+ line.endswith(",") or
+ line.endswith(")")
+ ):
+ continue
+ if line.startswith("static"):
+ continue
+ if "<const string" in line:
+ continue
+
+ if (_match_re1.search(line) is not None or
+ _match_re2.search(line) is not None):
+ errors.append((fn, lineno+1, error_msg))
+ return errors
+
+evaluate_matches = evaluate_matches
forbidden = [
'(std::string const,',
@@ -23,6 +53,8 @@
]
allowed = [
+ 'typedef map<const string,'
+' const std::string fullname1 = FS_CanonicalizeName(old_name);',
'(std::string const &,'
' std::string const & abc,',
' std::string const & = "abc",',
=== removed file 'cmake/codecheck/rules/illegal_space_after_opening_brace'
--- cmake/codecheck/rules/illegal_space_after_opening_brace 2010-11-01 12:12:18 +0000
+++ cmake/codecheck/rules/illegal_space_after_opening_brace 1970-01-01 00:00:00 +0000
@@ -1,63 +0,0 @@
-#!/usr/bin/python
-
-
-"""
-This catches an opening brace followed by a space, but it allows it if a
-comment begins there, such as "{ // comment".
-"""
-
-error_msg = "No space after opening brace allowed!"
-strip_comments_and_strings = True
-strip_macros = True
-
-import re
-class EvalMatches( object ):
- REGEXP = re.compile(r"""(?x)
-\{([ ]\s*.*)
-""")
-
- def __call__(self, lines, fn):
- errors = []
- curline = 0
- for l in lines:
- l = l.rstrip()
- curline += 1
- m = self.REGEXP.search(l)
- if m:
- g = m.group(1)
- if not len(g): continue
- if g[-1] == '\\': continue
-
- errors.append( (fn, curline, error_msg))
- return errors
-
-
-evaluate_matches = EvalMatches()
-
-
-forbidden = [
- '{ /',
- '{ / /',
- '{ h',
- '{ "h"',
-]
-
-allowed = [
- "if(blah) { \\",
- '\tif ((m_readyflags | thisflag) != 3) { // codepath a',
- r'// { This is ok',
- r'/// {{{ Like this',
- r'/* {{{ And this this */',
- r'{ // And this also',
- r'{',
- r'{/',
- r'{/ /',
- r'{h',
- r'{"h"',
- "namespace Widelands {\n",
- "// Do { what we want in comments",
- "buffer[i] = '{'",
- r" // FIXME instead of replacing < with { in chat messages.",
- "{ /* check number of arguments */",
- "{ // check number of arguments",
-]
=== removed file 'cmake/codecheck/rules/illegal_space_after_opening_bracket'
--- cmake/codecheck/rules/illegal_space_after_opening_bracket 2010-11-01 12:12:18 +0000
+++ cmake/codecheck/rules/illegal_space_after_opening_bracket 1970-01-01 00:00:00 +0000
@@ -1,23 +0,0 @@
-#!/usr/bin/python
-
-
-"""
-This catches an opening [ followed by a space or end of line.
-"""
-
-error_msg="No space or newline allowed after opening bracket."
-
-strip_comments_and_strings = True
-strip_macros = True
-regexp=r"""\[( |$|\n)"""
-
-forbidden = [
- '\tfloat a[ 2];',
-]
-
-allowed = [
- '[h',
- '//[',
- '// [',
- '// Do [ what you want ( in comments',
-]
=== removed file 'cmake/codecheck/rules/illegal_space_after_opening_parenthesis'
--- cmake/codecheck/rules/illegal_space_after_opening_parenthesis 2010-11-01 12:12:18 +0000
+++ cmake/codecheck/rules/illegal_space_after_opening_parenthesis 1970-01-01 00:00:00 +0000
@@ -1,35 +0,0 @@
-#!/usr/bin/python
-
-
-"""
-This catches an opening parenthesis followed by a space or end of line.
-"""
-
-error_msg="No space or newline allowed after opening parenthesis."
-
-strip_comments_and_strings = True
-strip_macros = True
-regexp=r"""\(( |$|\n)"""
-
-forbidden = [
- '( h',
- '( ',
- '(',
- '/(',
- '/ /(',
- '/ / (',
- '/ / /(',
- '/ / /(\nadjh',
-
- # Eriks tests
- ## illegal_character_after_opening_parenthesis.cc
- 'void f( float) {',
-]
-
-allowed = [
- '(h',
- '//(',
- '// (',
- '// (',
- '/* Convert \n * string blah ( \n */',
-]
=== modified file 'cmake/codecheck/rules/illegal_space_before'
--- cmake/codecheck/rules/illegal_space_before 2010-02-05 01:13:20 +0000
+++ cmake/codecheck/rules/illegal_space_before 2013-05-18 05:56:27 +0000
@@ -8,9 +8,11 @@
"""
error_msg = "No space before ), }, ; allowed!"
+# strip_comments_and_strings = True
regexp = r"""^([^/#"']|/([^/"']|"([^"]|\\")*"|'(\\[\'0nt]|[^\'])')|"([^"\]|\\"|\\[^"])*"|'(\\[\'0nt]|[^\'])')*/? []);,]"""
+
forbidden = [
' )',
' / )',
=== removed file 'cmake/codecheck/rules/illegal_token_after_closing_parenthesis_opened_on_earlier_line'
--- cmake/codecheck/rules/illegal_token_after_closing_parenthesis_opened_on_earlier_line 2010-11-01 12:45:13 +0000
+++ cmake/codecheck/rules/illegal_token_after_closing_parenthesis_opened_on_earlier_line 1970-01-01 00:00:00 +0000
@@ -1,95 +0,0 @@
-#!/usr/bin/python
-
-
-"""
-Make the whitespace_checker detect illegal tokens after a closing
-parenthesis that has its opening parenthesis on a previous line (only
-closing tokens are allowed there until the end of the line).
-"""
-
-import re
-
-class EvalMatches(object):
- _closing_parens = re.compile(r'''(?x)
-(\() | # Either an opening or
-(\))[ ]*[)}\],;]*[ ]*([^\s(;]) # Or a closing with an illegal token
-'''
-)
- _error_msg = "Found '%s', but only closing tokens are allowed after closing " \
- "parenthesis with corresponding opening parenthesis "\
- "on an earlier line"
- def __call__(self,lines,fn):
- errors = []
-
- open_parens = 0
- for lineno,line in enumerate(lines):
-
- last_opening_parens = open_parens
-
- # Find all closing parens
- open_parens_on_line = 0
- for m in self._closing_parens.finditer(line):
- if m.group(1) == '(':
- open_parens += 1
- open_parens_on_line += 1
- else:
- open_parens -= m.group(0).count(')')
- open_parens_on_line -= m.group(0).count(')')
- if last_opening_parens and open_parens_on_line < 0 and \
- m.group(3) not in ')}],;':
- g = m.group(3)
- # pure virtual function?
- if not line.strip().endswith("= 0;"):
- errors.append((fn,lineno+1,self._error_msg % g))
-
- open_parens = last_opening_parens + line.count('(') - line.count(')')
-
-
-
- return errors
-
-evaluate_matches = EvalMatches()
-
-
-strip_macros = True
-strip_comments_and_strings = True
-
-forbidden = [
-# Eriks tests
-## illegal_character_after_closing_brace.cc
-"""bool func(bool const a, bool const b) {
-\treturn
-\t\tfunc
-\t\t\t(a,
-\t\t\t func(b, a)) == func(b, func(b, a));
-}""",
-
-"""bool fund(bool const a, bool const b) {
-\treturn
-\t\tfunc
-\t\t\t(func
-\t\t\t \t(a,
-\t\t\t \t func(b, a)), func(b, func(b, a)));
-}""",
-
-]
-
-allowed = [
-"""std::set<std::string> const & operator[] (size_t const i) const {
-\t}
-\tstd::set<std::string> & operator[] (size_t const i) {
-\t}
-""",
-
-"""(dynamic_cast<Road const *>(pimm) &&
-\t\t\t fc.field->get_caps() & BUILDCAPS_FLAG));""",
-
-"""snprintf
-\t\t(buffer, sizeof(buffer),
-\t\t _("%u%% built"), (get_built_per64k() * 100) >> 16);""",
-"""blah
- (int a, int b,
- int c) = 0;
-""",
-
-]
=== removed file 'cmake/codecheck/rules/line_starting_with_space_followed_by_control_structure'
--- cmake/codecheck/rules/line_starting_with_space_followed_by_control_structure 2010-02-05 01:13:20 +0000
+++ cmake/codecheck/rules/line_starting_with_space_followed_by_control_structure 1970-01-01 00:00:00 +0000
@@ -1,43 +0,0 @@
-#!/usr/bin/python
-
-
-"""
-Lines with control structures affect how editors indent the controlled lines
-following them. So an existing line of that kind that is badly indented can
-cause newly added code to become badly indented. Therefore it is especially
-important that the control structures are correctly indented.
-
-This does not yet include for loops, because there are still too many of them
-that need fixing and they should eventually be replaced with iteration macros
-anyway.
-
-I disagree with the macros. I do not think they add to the clarity of the code.
- -- SirVer
-"""
-
-error_msg = "Bad indentation."
-
-strip_comments_and_strings = True
-strip_macros = True
-regexp=r"""^ * +(\{|case|else|try|(catch|if|switch|while) *\()"""
-
-forbidden = [
- ' {',
- ' else',
- ' if (a)',
- ' switch (a)',
- ' while (a)',
-]
-
-allowed = [
- ' {',
- ' }',
- ' else',
- ' if (a)',
- ' switch (a)',
- ' while (a)',
-"""#define iterate_players_existing(p, nr_players, egbase, player) \\
- iterate_player_numbers(p, nr_players) \\
- if (Widelands::Player * const player = (egbase).get_player(p)) \\""",
-
-]
=== modified file 'cmake/codecheck/rules/local_inlude_with_dir'
--- cmake/codecheck/rules/local_inlude_with_dir 2010-02-05 01:13:20 +0000
+++ cmake/codecheck/rules/local_inlude_with_dir 2013-05-18 05:56:27 +0000
@@ -1,7 +1,7 @@
#!/usr/bin/python -tt
"""
-This checks for
+This checks for
#include "somedir/file.h"
@@ -13,11 +13,11 @@
def evaluate_matches(lines, fn):
errors = []
-
+
splitted_fn = fn.rsplit('/')
if len(splitted_fn) == 1:
return []
-
+
for lineno,line in enumerate(lines):
if not line.startswith("#include"):
continue
@@ -26,15 +26,15 @@
if inc[0] != '"':
continue
inc = inc.strip('"')
-
+
splitted_inc = inc.rsplit('/',1)
if len(splitted_inc) == 1: # "file.h" not "dir/file.h"
continue
-
+
subdirdepth = splitted_inc[0].count('/') + 1
dir = '/'.join(splitted_fn[-subdirdepth-1:-1])
-
+
split_dir = splitted_inc[0]
if split_dir == dir:
=== removed file 'cmake/codecheck/rules/missing_padding'
--- cmake/codecheck/rules/missing_padding 2012-12-15 18:40:59 +0000
+++ cmake/codecheck/rules/missing_padding 1970-01-01 00:00:00 +0000
@@ -1,379 +0,0 @@
-#!/usr/bin/env python -tt
-# encoding: utf-8
-#
-
-"""
-Checking for forbidden padding.
-TypeName* and TypeName& are okay, as are TypeName * and TypeName &.
-"""
-
-error_msg="Missing padding for operator. Needs a space before and after."
-
-import re
-
-# It is easier to search for invalids than for 'NOT' invalids
-regexp = re.compile(r"""(?x)
-([^\s](?:(?:&&)|(?:\|\|)))|
-((?:(?:&&)|(?:\|\|))[^\s])|
-([^\s>(&*:!{+\-[.](?<!operator)[*&][^*\s>)},])| # Type*, Type&, operator
-([+\-*/|^&!<]?={1,2}[^\s=])| # '+= a', 'a== a', 'a!= a'
-([^\s=!+-/^*/&|^<>r%][+\-*/^&|!<>%]?={1,2})| # ' +=a', ' ==a', ' !=a', doesn't match 'r=' for operator=
-
-([^-<]>[^\s=&>*(:,);])| # 'a >b'
-
-([^\s][/^\%](?!=))| # '/ a'
-([/^\%][^=\s])|
-([^\s\-eE([{]-[^\s=\->])| # -> and -= and unary -, also 8e-1
-([^\s+]\+[^\s=+]) # +=
-"""
-)
-
-def match_function( lines, fn ):
- errors = []
- for lineno,line in enumerate(lines):
- line = line.strip()
- if not len(line) or line[0] == '#':
- continue
-
- lineno += 1
-
- if regexp.search(line):
- errors.append( (fn, lineno, error_msg) )
-
- return errors
-
-strip_comments_and_strings = True
-
-evaluate_matches = match_function
-
-forbidden = [
- " a== b",
- " a ==b",
- " a !=b",
- " a!= b",
- "a>= b",
- "a >=b",
- "b<= a",
- "b <=a",
- #"b< a", could also be std::vector<a
- #"b <a", could also be std::vector<hai>
- #"b> a", could also be std::vector<hallo> hi;
- "b >a",
-
- ' a&& b',
- ' a &&b',
- ' a|| b',
- ' a ||b',
-
- 'char a = a^ a;',
- 'char a = a ^a;',
-
- # Eriks tests
- ## missing_padding.cc
- 'char a=a;',
- 'char a = a^a;',
- 'char a = a%a;',
- 'char a = a/a;',
- 'char a = a*a;',
- 'char a = a+a;',
- 'char a = a-a;',
- 'char A =A;',
- 'char A = A^A;',
- 'char A = A%A;',
- 'char A = A/A;',
- 'char A = A*A;',
- 'char A = A+A;',
- 'char A = A-A;',
-
- 'char b=b;',
- 'char b = b^b;',
- 'char b = b%b;',
- 'char b = b/b;',
- 'char b = b*b;',
- 'char b = b+b;',
- 'char b = b-b;',
- 'char B =B;',
- 'char B = B^B;',
- 'char B = B%B;',
- 'char B = B/B;',
- 'char B = B*B;',
- 'char B = B+B;',
- 'char B = B-B;',
-
- 'char _ =_;',
- 'char _ = _^_;',
- 'char _ = _%_;',
- 'char _ = _/_;',
- 'char _ = _*_;',
- 'char _ = _+_;',
- 'char _ = _-_;',
-
- 'char x0 =010;',
- 'char x0 = 010^010;',
- 'char x0 = 010%010;',
- 'char x0 = 010/010;',
- 'char x0 = 010*010;',
- 'char x0 = 010+010;',
- 'char x0 = 010-010;',
-
- 'char x1 =1;',
- 'char x1 = 1^1;',
- 'char x1 = 1%1;',
- 'char x1 = 1/1;',
- 'char x1 = 1*1;',
- 'char x1 = 1+1;',
- 'char x1 = 1-1;',
-
- 'char const * str ="";',
-
- 'char ch =' ';',
-
- 'a^= a;',
- 'a ^=a;',
- 'a^=a;',
- 'a/g= a;',
- 'a /g=a;',
- 'a/g=a;',
- 'a*= a;',
- 'a *=a;',
- 'a*=a;',
- 'a-= a;',
- 'a -=a;',
- 'a-=a;',
- 'a+= a;',
- 'a +=a;',
- 'a+=a;',
- 'a%=a;',
- 'a%= a;',
- 'a %=a;',
-
- 'A^= A;',
- 'A ^=A;',
- 'A^=A;',
- 'A/g= A;',
- 'A /g=A;',
- 'A/g=A;',
- 'A*= A;',
- 'A *=A;',
- 'A*=A;',
- 'A-= A;',
- 'A -=A;',
- 'A-=A;',
- 'A+= A;',
- 'A +=A;',
- 'A+=A;',
-
- '_^= _;',
- '_ ^=_;',
- '_^=_;',
- '_/g= _;',
- '_ /g=_;',
- '_/g=_;',
- '_*= _;',
- '_ *=_;',
- '_*=_;',
- '_-= _;',
- '_ -=_;',
- '_-=_;',
- '_+= _;',
- '_ +=_;',
- '_+=_;',
-
-]
-
-allowed = [
- "char** argv",
- "AnimationGfx(const IImageLoader&, AnimationData const * data);",
- "RoutingNode* a;",
- "Blahtype& b;",
- "std::vector<RoutingNode*> & nodes",
-
- 'type_a& aa = aa;',
- 'type_A& AA = AA;',
- 'type_b& bb = bb;',
- 'type_B& BB = BB;',
- 'type_c& cc = cc;',
- 'type_C& CC = AA;',
- 'type_d& dd = dd;',
- 'type_D& DD = DD;',
- 'type_e& ee = ee;',
- 'type_E& EE = EE;',
- 'type_f& ff = ff;',
- 'type_F& FF = FF;',
- 'type_g& gg = gg;',
- 'type_G& GG = GG;',
- 'type_h& hh = hh;',
- 'type_H& HH = HH;',
- 'type_i& ii = ii;',
- 'type_I& II = II;',
- 'type_j& jj = jj;',
- 'type_J& JJ = JJ;',
- 'type_k& kk = kk;',
- 'type_K& KK = KK;',
- 'type_l& ll = ll;',
- 'type_L& LL = LL;',
- 'type_m& mm = mm;',
- 'type_M& MM = MM;',
- 'type_n& nn = nn;',
- 'type_N& NN = NN;',
- 'type_o& oo = oo;',
- 'type_O& OO = OO;',
- 'type_p& pp = pp;',
- 'type_P& PP = PP;',
- 'type_q& qq = qq;',
- 'type_Q& QQ = QQ;',
- 'type_r& rr = rr;',
- 'type_R& RR = RR;',
- 'type_s& ss = ss;',
- 'type_S& SS = SS;',
- 'type_t& tt = tt;',
- 'type_T& TT = TT;',
- 'type_u& uu = uu;',
- 'type_U& UU = UU;',
- 'type_v& vv = vv;',
- 'type_V& VV = VV;',
- 'type_w& ww = ww;',
- 'type_W& WW = WW;',
- 'type_x& xx = xx;',
- 'type_X& XX = XX;',
- 'type_y& yy = yy;',
- 'type_Y& YY = YY;',
- 'type_z& zz = zz;',
- 'type_Z& ZZ = ZZ;',
- 'type_a* aaa;',
- 'type_b* bbb;',
- 'type_c* ccc;',
- 'type_d* ddd;',
- 'type_e* eee;',
- 'type_f* fff;',
- 'type_g* ggg;',
- 'type_h* hhh;',
- 'type_i* iii;',
- 'type_j* jjj;',
- 'type_k* kkk;',
- 'type_l* lll;',
- 'type_m* mmm;',
- 'type_n* nnn;',
- 'type_o* ooo;',
- 'type_p* ppp;',
- 'type_q* qqq;',
- 'type_r* rrr;',
- 'type_s* sss;',
- 'type_t* ttt;',
- 'type_u* uuu;',
- 'type_v* vvv;',
- 'type_w* www;',
- 'type_x* xxx;',
- 'type_y* yyy;',
- 'type_z* zzz;',
- 'type_A* AAA;',
- 'type_B* BBB;',
- 'type_C* CCC;',
- 'type_D* DDD;',
- 'type_E* EEE;',
- 'type_F* FFF;',
- 'type_G* GGG;',
- 'type_H* HHH;',
- 'type_I* III;',
- 'type_J* JJJ;',
- 'type_K* KKK;',
- 'type_L* LLL;',
- 'type_M* MMM;',
- 'type_N* NNN;',
- 'type_O* OOO;',
- 'type_P* PPP;',
- 'type_Q* QQQ;',
- 'type_R* RRR;',
- 'type_S* SSS;',
- 'type_T* TTT;',
- 'type_U* UUU;',
- 'type_V* VVV;',
- 'type_W* WWW;',
- 'type_X* XXX;',
- 'type_Y* YYY;',
- 'type_Z* ZZZ;',
- "RoutingNode* a;",
- "Blahtype& b;",
- "RoutingNode * a;",
- "Blahtype & b;",
- "/** Some comment **/",
- "std::vector<RoutingNode *> & nodes",
- "if (a && b)",
- "\tOpen.push(&start);",
- "\t\t*reinterpret_cast<std::vector<RoutingNode *>*>(&m_flags);",
- "std::vector<RoutingNode *>& nodes",
- "/* warehouses can determine max idle priority*/",
- "blah // I *wanna* do that",
- "&*m_stack.rbegin()",
-
- "(std::set<std::string>, j.current->second, i)",
-
- # > <
- "r = (palette[i].r * shade) >> 8;",
- "std::vector<High>",
- "std::vector<State>::iterator it = m_stack.end();",
-
- "v->get_string()", # pointers are fine
-
- # Allow includes
- "#include <sys/types.h>",
-
-
- # Ignore strings & comments
- "\tif (*i.current == '%') {",
- "if (calc_linewidth(font, cur_word) > (max_width /*/ 2*/)) {",
-
-
- # * Pointer to pointer
- "func(int **r);",
- "void (a::*b)",
- "if (!*ppgrid) {",
- "void MiniMap::toggle(Layers button) {*m_view.m_flags ^= button;}",
- "m_loaded_obj[&object] = false;",
- "m_loaded_obj[*object] = false;",
- "(_callback_argument_this.*_callback_function)();",
- "friend struct Table<void *>;",
-
- # Unary minus
- "-1",
- "func(-1);",
- "8.46126929e-5",
- "-8.46126929e-5",
-
- # Operator=
- "int someclass::operator= (int)",
- "int someclass::operator* (int)",
- "int someclass::operator== (int)",
-
- # increment, decrement
- "incr++;",
- "++incr;",
- "--decr;",
- "decr--;",
- "++*digit_to_increment;",
-
- # +=, -=
- "result += it",
- "result -= it",
-
- # Logical
- "a && b",
- "a || b",
-
- # compares
- "a == b",
- "a != b",
- "a >= b",
- "b <= a",
- "b < a",
- "b > a",
- "AreaWatcher(const Player_Area<>);",
- "void func (Player_Area<Area>);",
- "friend class NoteReceiver<T>;",
-
- 'a %= a;',
-
- 'Texture const & /* f_r_texture */',
- 'int32_t estimate(Map & /* map */, FCoords /* pos */) const {return 0;}',
-
-]
=== modified file 'cmake/codecheck/rules/missing_space_after_control_structure_keyword'
--- cmake/codecheck/rules/missing_space_after_control_structure_keyword 2010-02-05 01:13:20 +0000
+++ cmake/codecheck/rules/missing_space_after_control_structure_keyword 2013-05-18 05:56:27 +0000
@@ -8,18 +8,18 @@
structure keyword, for example "meanwhile(parameter)".
"""
-error_msg ="A space is mandatory after catch/for/if/switch/throw/while."
+error_msg ="A space is mandatory after catch/for/if/switch/while."
-regexp=r"""[^_a-zA-Z0-9](catch|for|if|switch|throw|while)\("""
+regexp=r"""[^_a-zA-Z0-9](catch|for|if|switch|while)\("""
forbidden = [
' for(;;)',
' catch(...) {',
' while(true)',
+]
+
+allowed = [
" throw('\n')",
-]
-
-allowed = [
' meanwhile(true)',
' while (true)',
' for (;;)',
=== removed file 'cmake/codecheck/rules/multiline_single-statement-controlling_control-statement_not_wrapped_before_controlled_statement'
--- cmake/codecheck/rules/multiline_single-statement-controlling_control-statement_not_wrapped_before_controlled_statement 2010-02-05 01:13:20 +0000
+++ cmake/codecheck/rules/multiline_single-statement-controlling_control-statement_not_wrapped_before_controlled_statement 1970-01-01 00:00:00 +0000
@@ -1,70 +0,0 @@
-#!/usr/bin/python
-
-
-"""
-This was added to find some of the stuff that annoys Nicolai, such as:
- if (a) throw wexception
- ("Message explaining what went wrong, using format "
- "argument such as %u, %ill and %s",
- 7, -9380350846789, "hej");
-
-He requires it to be formatted like this instead:
- if (a)
- throw wexception
- ...
-
-So a line with "for (a)", "if (a)" or "while (a)" must end with one of the
-characters in the string "){};\". Although a comment at the end is allowed
-(therefore the complex regexp).
-
-It would indeed be inconsistent to wrap within the controlled statement without
-wrapping before it. A justification to do that would be to save vertical screen
-space.
-
-Do the same for do, else and return statements. Unfortunately it will miss
-lines ending with do or else followed by something very short (a single letter,
- like "do a" or
- "else a")
-because it has to allow "do if" and "else if".
-"""
-
-error_msg = """Multiline conditional should break after conditional. if (a) blah... -> if (a) \\n blah"""
-
-regexp=r"""(?x)
-^
-(
- [^/\#"']|/([^/"']|"([^"\]|\\"|\\[^"])*"|'(\\[\'0nt]|[^\'])')|"([^"]|\\")*"|'(\\[\'0nt]|[^\'])'
-)*
-(
- (^|\t)((do|else)[ ]([^/i]|(i[^f]))|return[ ]+)|(for|if|while)[ ]*\((/[^/*]|[^/])*\)[ ]*
-)
-(/[^/*]|[^/])*
-[^){};\\ \n]$"""
-
-forbidden = [
- 'do hl',
- ' do gam',
- 'else hl',
- ' else gam',
- 'return a ?',
- ' return hlj',
- 'if (condition) do_something',
- 'if (a) throw wexception',
-]
-
-allowed = [
- ' do if',
- ' do // something',
- ' else if',
- ' else // something',
- ' return a ? b : c;',
- ' return',
- '\return this is a doxygen comment',
- '\todo',
- 'if (condition) do_something();',
- 'if (c) throw wexception("Something went wrong.");',
- 'if (c)',
- ' ("calculated value for (%i, %i)",',
- '\t\treturn m_nb; ',
- '\t\treturn m_nb;\n',
-]
=== removed file 'cmake/codecheck/rules/parenthesis_not_closed_before_end_of_line'
--- cmake/codecheck/rules/parenthesis_not_closed_before_end_of_line 2010-02-05 01:13:20 +0000
+++ cmake/codecheck/rules/parenthesis_not_closed_before_end_of_line 1970-01-01 00:00:00 +0000
@@ -1,54 +0,0 @@
-#!/usr/bin/env python -tt
-# encoding: utf-8
-#
-
-"""
-Catches something like
-blah (kjhdsfjh +
-
-which should be
-blah
- (jdhsf +
-"""
-
-def check_function(lines,fn):
- errors = []
- for lineno,line in enumerate(lines):
- line = line.strip()
- lineno += 1
- opening_parens = line.count('(')
- closing_parens = line.count(')')
- if opening_parens > closing_parens and line[0] != '(':
- errors.append( (fn, lineno,
- "Parenthesis not closed before end of "
- "line must be at line begin")
- )
-
- return errors
-
-strip_comments_and_strings = True
-strip_macros = True
-
-evaluate_matches = check_function
-
-forbidden = [
-"""float g(float, float) {
-\treturn (0.0 +
-\t\tg(1.1, 2.2));
-}""",
-]
-
-allowed = [
-"""float g(float, float) {
-\treturn
-\t\t(0.0 +
-\t\t g(1.1, 2.2));
-}""",
-
-"""\tstd::string newvisi = s->get_string("newvisi", "");""",
-
-# Ignore macros
-"""#if (defined(WIN32) || defined (WINDOWS) || \\
-\tdefined (_WINDOWS)) && defined(CALLBACK) && \\
-\tdefined (USEWINDOWS_CALLBACK)""",
-]
=== removed file 'cmake/codecheck/rules/space_as_indentation'
--- cmake/codecheck/rules/space_as_indentation 2010-02-05 01:13:20 +0000
+++ cmake/codecheck/rules/space_as_indentation 1970-01-01 00:00:00 +0000
@@ -1,28 +0,0 @@
-#!/usr/bin/env python -tt
-# encoding: utf-8
-#
-
-"""
-Cry when space appears as first character on a line. Indentation should be done with tabs.
-There is no reason to have spaces as the first line
-
-This is not obligatory for macros, because of the Alignement of the \\ at the end
-"""
-
-error_msg="Use tabs for indentation."
-
-strip_comments_and_strings = True
-strip_macros = True
-regexp = r"^ +"
-
-forbidden = [
- " if(a)\n",
-]
-
-allowed = [
- "if\n",
- "\tif(a) {\n",
- " // Comment is ok",
- "/*\n * Multiline comment too */",
- "#in macros\\\nHi\\\n Hi", # \\\n it's ok too",
-]
=== modified file 'src/HTMLReferences.h'
--- src/HTMLReferences.h 2013-02-10 19:36:24 +0000
+++ src/HTMLReferences.h 2013-05-18 05:56:27 +0000
@@ -31,16 +31,23 @@
#include <string>
struct HTMLReferences {
- enum Role {Input, Output, Madeof, Become, Employ, End};
- const std::set<std::string> & operator[] (size_t const i) const {
- assert(i < End);
- return references[i];
- }
- std::set<std::string> & operator[] (size_t const i) {
- assert(i < End);
- return references[i];
- }
- std::set<std::string> references[End]; /// indexed by Referencing_Role
+ enum Role {
+ Input,
+ Output,
+ Madeof,
+ Become,
+ Employ,
+ End
+ };
+ const std::set<std::string>& operator[](size_t const i) const {
+ assert(i < End);
+ return references[i];
+ }
+ std::set<std::string>& operator[](size_t const i) {
+ assert(i < End);
+ return references[i];
+ }
+ std::set<std::string> references[End]; /// indexed by Referencing_Role
};
#endif
=== modified file 'src/TribeBasicInfo.h'
--- src/TribeBasicInfo.h 2012-02-15 21:25:34 +0000
+++ src/TribeBasicInfo.h 2013-05-18 05:56:27 +0000
@@ -27,14 +27,14 @@
/// Basic information about the tribe that is determined only from the conf
/// file and needed before the actual game.
struct TribeBasicInfo {
- std::string name;
-
- /// Relative position of this tribe in a list of tribes.
- uint8_t uiposition;
-
- typedef std::pair<std::string, std::string> Initialization;
- typedef std::vector<Initialization> Initializations;
- Initializations initializations;
+ std::string name;
+
+ /// Relative position of this tribe in a list of tribes.
+ uint8_t uiposition;
+
+ typedef std::pair<std::string, std::string> Initialization;
+ typedef std::vector<Initialization> Initializations;
+ Initializations initializations;
};
#endif
=== modified file 'src/ai/ai_help_structs.cc'
--- src/ai/ai_help_structs.cc 2012-09-21 21:36:07 +0000
+++ src/ai/ai_help_structs.cc 2013-05-18 05:56:27 +0000
@@ -21,66 +21,59 @@
#include "logic/player.h"
#include "upcast.h"
-
namespace Widelands {
// FindNodeWithFlagOrRoad
-bool FindNodeWithFlagOrRoad::accept (const Map &, FCoords fc) const
-{
- if (upcast(PlayerImmovable const, pimm, fc.field->get_immovable()))
- return
- pimm->get_economy() != economy
- and
- (dynamic_cast<Flag const *>(pimm)
- or
- (dynamic_cast<Road const *>(pimm) &&
- (fc.field->nodecaps() & BUILDCAPS_FLAG)));
- return false;
+bool FindNodeWithFlagOrRoad::accept(const Map&, FCoords fc) const {
+ if (upcast(PlayerImmovable const, pimm, fc.field->get_immovable()))
+ return pimm->get_economy() != economy and(dynamic_cast<Flag const*>(pimm)
+ or(dynamic_cast<Road const*>(pimm) &&
+ (fc.field->nodecaps() & BUILDCAPS_FLAG)));
+ return false;
}
-
// CheckStepRoadAI
-bool CheckStepRoadAI::allowed
- (Map & map, FCoords, FCoords end, int32_t, CheckStep::StepId const id)
- const
-{
- uint8_t endcaps = player->get_buildcaps(end);
-
- // Calculate cost and passability
- if (!(endcaps & movecaps))
- return false;
-
- // Check for blocking immovables
- if (BaseImmovable const * const imm = map.get_immovable(end))
- if (imm->get_size() >= BaseImmovable::SMALL) {
- if (id != CheckStep::stepLast && !openend)
- return false;
-
- if (dynamic_cast<Flag const *>(imm))
- return true;
-
- if (not dynamic_cast<Road const *>(imm) || !(endcaps & BUILDCAPS_FLAG))
- return false;
- }
-
- return true;
+bool CheckStepRoadAI::allowed(Map& map,
+ FCoords,
+ FCoords end,
+ int32_t,
+ CheckStep::StepId const id) const {
+ uint8_t endcaps = player->get_buildcaps(end);
+
+ // Calculate cost and passability
+ if (!(endcaps & movecaps))
+ return false;
+
+ // Check for blocking immovables
+ if (BaseImmovable const* const imm = map.get_immovable(end))
+ if (imm->get_size() >= BaseImmovable::SMALL) {
+ if (id != CheckStep::stepLast && !openend)
+ return false;
+
+ if (dynamic_cast<Flag const*>(imm))
+ return true;
+
+ if (not dynamic_cast<Road const*>(imm) || !(endcaps & BUILDCAPS_FLAG))
+ return false;
+ }
+
+ return true;
}
-bool CheckStepRoadAI::reachabledest(Map & map, FCoords const dest) const
-{
- NodeCaps const caps = dest.field->nodecaps();
-
- if (!(caps & movecaps)) {
- if (!((movecaps & MOVECAPS_SWIM) && (caps & MOVECAPS_WALK)))
- return false;
-
- if (!map.can_reach_by_water(dest))
- return false;
- }
-
- return true;
+bool CheckStepRoadAI::reachabledest(Map& map, FCoords const dest) const {
+ NodeCaps const caps = dest.field->nodecaps();
+
+ if (!(caps & movecaps)) {
+ if (!((movecaps & MOVECAPS_SWIM) && (caps & MOVECAPS_WALK)))
+ return false;
+
+ if (!map.can_reach_by_water(dest))
+ return false;
+ }
+
+ return true;
}
}
=== modified file 'src/ai/ai_help_structs.h'
--- src/ai/ai_help_structs.h 2013-02-10 19:36:24 +0000
+++ src/ai/ai_help_structs.h 2013-05-18 05:56:27 +0000
@@ -36,244 +36,212 @@
class MilitarySite;
struct CheckStepRoadAI {
- CheckStepRoadAI(Player * const pl, uint8_t const mc, bool const oe)
- : player(pl), movecaps(mc), openend(oe)
- {}
-
- void set_openend (bool const oe) {openend = oe;}
-
- bool allowed
- (Map &, FCoords start, FCoords end, int32_t dir, CheckStep::StepId)
- const;
- bool reachabledest(Map &, FCoords dest) const;
-
- Player * player;
- uint8_t movecaps;
- bool openend;
+ CheckStepRoadAI(Player* const pl, uint8_t const mc, bool const oe)
+ : player(pl), movecaps(mc), openend(oe) {}
+
+ void set_openend(bool const oe) { openend = oe; }
+
+ bool allowed(Map&, FCoords start, FCoords end, int32_t dir, CheckStep::StepId) const;
+ bool reachabledest(Map&, FCoords dest) const;
+
+ Player* player;
+ uint8_t movecaps;
+ bool openend;
};
-
struct FindNodeUnowned {
- bool accept (const Map &, const FCoords & fc) const {
- // when looking for unowned terrain to acquire, we are actually
- // only interested in fields we can walk on.
- // Fields should either be completely unowned or owned by an opposing player
- return
- (fc.field->nodecaps() & MOVECAPS_WALK)
- &&
- ((fc.field->get_owned_by() == 0)
- || player->is_hostile(*game.get_player(fc.field->get_owned_by())))
- && (!onlyenemies || (fc.field->get_owned_by() != 0));
- }
-
- //int8_t playernum;
- Player * player;
- Game & game;
- bool onlyenemies;
-
- FindNodeUnowned(Player * p, Game & g, bool oe = false)
- : player(p), game(g), onlyenemies(oe)
- {}
+ bool accept(const Map&, const FCoords& fc) const {
+ // when looking for unowned terrain to acquire, we are actually
+ // only interested in fields we can walk on.
+ // Fields should either be completely unowned or owned by an opposing player
+ return (fc.field->nodecaps() & MOVECAPS_WALK) &&
+ ((fc.field->get_owned_by() == 0) ||
+ player->is_hostile(*game.get_player(fc.field->get_owned_by()))) &&
+ (!onlyenemies || (fc.field->get_owned_by() != 0));
+ }
+
+ //int8_t playernum;
+ Player* player;
+ Game& game;
+ bool onlyenemies;
+
+ FindNodeUnowned(Player* p, Game& g, bool oe = false) : player(p), game(g), onlyenemies(oe) {}
};
-
struct FindNodeWater {
- bool accept(const Map & map, const FCoords & coord) const {
- return
- (map.world().terrain_descr(coord.field->terrain_d()).get_is()
- & TERRAIN_WATER)
- ||
- (map.world().terrain_descr(coord.field->terrain_r()).get_is()
- & TERRAIN_WATER);
- }
+ bool accept(const Map& map, const FCoords& coord) const {
+ return (map.world().terrain_descr(coord.field->terrain_d()).get_is() & TERRAIN_WATER) ||
+ (map.world().terrain_descr(coord.field->terrain_r()).get_is() & TERRAIN_WATER);
+ }
};
-
struct FindNodeWithFlagOrRoad {
- Economy * economy;
- bool accept(const Map &, FCoords) const;
+ Economy* economy;
+ bool accept(const Map&, FCoords) const;
};
-
struct NearFlag {
- Flag const * flag;
- int32_t cost;
- int32_t distance;
-
- NearFlag (const Flag & f, int32_t const c, int32_t const d) :
- flag(&f), cost(c), distance(d)
- {}
-
- bool operator< (const NearFlag & f) const {return cost > f.cost;}
-
- bool operator== (Flag const * const f) const {return flag == f;}
+ Flag const* flag;
+ int32_t cost;
+ int32_t distance;
+
+ NearFlag(const Flag& f, int32_t const c, int32_t const d) : flag(&f), cost(c), distance(d) {}
+
+ bool operator<(const NearFlag& f) const { return cost > f.cost; }
+
+ bool operator==(Flag const* const f) const { return flag == f; }
};
-
struct CompareDistance {
- bool operator() (const NearFlag & a, const NearFlag & b) const {
- return a.distance < b.distance;
- }
+ bool operator()(const NearFlag& a, const NearFlag& b) const { return a.distance < b.distance; }
};
-
struct WalkableSpot {
- Coords coords;
- bool hasflag;
-
- int32_t cost;
- void * eco;
-
- int16_t from;
- int16_t neighbours[6];
+ Coords coords;
+ bool hasflag;
+
+ int32_t cost;
+ void* eco;
+
+ int16_t from;
+ int16_t neighbours[6];
};
}
struct BlockedField {
- Widelands::FCoords coords;
- int32_t blocked_until;
+ Widelands::FCoords coords;
+ int32_t blocked_until;
- BlockedField(Widelands::FCoords c, int32_t until)
- :
- coords(c),
- blocked_until(until)
- {}
+ BlockedField(Widelands::FCoords c, int32_t until) : coords(c), blocked_until(until) {}
};
struct BuildableField {
- Widelands::FCoords coords;
-
- int32_t next_update_due;
-
- bool reachable;
- bool preferred;
- bool avoid_military;
- bool enemy_nearby;
-
- uint8_t unowned_land_nearby;
-
- uint8_t trees_nearby;
- uint8_t stones_nearby;
- uint8_t water_nearby;
- uint8_t space_consumers_nearby;
-
- int16_t military_influence;
-
- std::vector<uint8_t> consumers_nearby;
- std::vector<uint8_t> producers_nearby;
-
- BuildableField (const Widelands::FCoords & fc)
- :
- coords (fc),
- next_update_due (0),
- reachable (false),
- preferred (false),
- avoid_military(0),
- enemy_nearby(0),
- unowned_land_nearby(0),
- trees_nearby (0),
- stones_nearby (0),
- water_nearby(0),
- space_consumers_nearby(0),
- military_influence(0)
- {}
+ Widelands::FCoords coords;
+
+ int32_t next_update_due;
+
+ bool reachable;
+ bool preferred;
+ bool avoid_military;
+ bool enemy_nearby;
+
+ uint8_t unowned_land_nearby;
+
+ uint8_t trees_nearby;
+ uint8_t stones_nearby;
+ uint8_t water_nearby;
+ uint8_t space_consumers_nearby;
+
+ int16_t military_influence;
+
+ std::vector<uint8_t> consumers_nearby;
+ std::vector<uint8_t> producers_nearby;
+
+ BuildableField(const Widelands::FCoords& fc)
+ : coords(fc),
+ next_update_due(0),
+ reachable(false),
+ preferred(false),
+ avoid_military(0),
+ enemy_nearby(0),
+ unowned_land_nearby(0),
+ trees_nearby(0),
+ stones_nearby(0),
+ water_nearby(0),
+ space_consumers_nearby(0),
+ military_influence(0) {}
};
struct MineableField {
- Widelands::FCoords coords;
-
- int32_t next_update_due;
-
- bool reachable;
- bool preferred;
-
- int32_t mines_nearby;
-
- MineableField (const Widelands::FCoords & fc) :
- coords (fc),
- next_update_due(0),
- reachable (false),
- preferred (false),
- mines_nearby(0)
- {}
+ Widelands::FCoords coords;
+
+ int32_t next_update_due;
+
+ bool reachable;
+ bool preferred;
+
+ int32_t mines_nearby;
+
+ MineableField(const Widelands::FCoords& fc)
+ : coords(fc), next_update_due(0), reachable(false), preferred(false), mines_nearby(0) {}
};
struct EconomyObserver {
- Widelands::Economy & economy;
- std::list<Widelands::Flag const *> flags;
- int32_t next_connection_try;
- uint32_t failed_connection_tries;
+ Widelands::Economy& economy;
+ std::list<Widelands::Flag const*> flags;
+ int32_t next_connection_try;
+ uint32_t failed_connection_tries;
- EconomyObserver (Widelands::Economy & e) : economy(e) {
- next_connection_try = 0;
- failed_connection_tries = 0;
- }
+ EconomyObserver(Widelands::Economy& e) : economy(e) {
+ next_connection_try = 0;
+ failed_connection_tries = 0;
+ }
};
struct BuildingObserver {
- char const * name;
- Widelands::Building_Index id;
- Widelands::Building_Descr const * desc;
-
- enum {
- BORING,
- CONSTRUCTIONSITE,
- PRODUCTIONSITE,
- MILITARYSITE,
- WAREHOUSE,
- TRAININGSITE,
- MINE
- } type;
-
- bool is_basic; // is a "must" to have for the ai
- bool prod_build_material;
- bool recruitment; // is "producing" workers?
-
- bool is_buildable;
-
- bool need_trees; // lumberjack = true
- bool need_stones; // quarry = true
- bool need_water; // fisher, fish_breeder = true
- bool space_consumer; // farm, vineyard... = true
-
- bool unoccupied; // >= 1 building unoccupied ?
-
- int32_t mines; // type of resource it mines
- uint16_t mines_percent; // % of res it can mine
-
- uint32_t current_stats;
-
- std::vector<int16_t> inputs;
- std::vector<int16_t> outputs;
- int16_t production_hint;
-
- int32_t cnt_built;
- int32_t cnt_under_construction;
-
- int32_t total_count() const {return cnt_built + cnt_under_construction;}
- bool buildable(Widelands::Player & player) {
- return is_buildable && player.is_building_type_allowed(id);
- }
+ char const* name;
+ Widelands::Building_Index id;
+ Widelands::Building_Descr const* desc;
+
+ enum {
+ BORING,
+ CONSTRUCTIONSITE,
+ PRODUCTIONSITE,
+ MILITARYSITE,
+ WAREHOUSE,
+ TRAININGSITE,
+ MINE
+ } type;
+
+ bool is_basic; // is a "must" to have for the ai
+ bool prod_build_material;
+ bool recruitment; // is "producing" workers?
+
+ bool is_buildable;
+
+ bool need_trees; // lumberjack = true
+ bool need_stones; // quarry = true
+ bool need_water; // fisher, fish_breeder = true
+ bool space_consumer; // farm, vineyard... = true
+
+ bool unoccupied; // >= 1 building unoccupied ?
+
+ int32_t mines; // type of resource it mines
+ uint16_t mines_percent; // % of res it can mine
+
+ uint32_t current_stats;
+
+ std::vector<int16_t> inputs;
+ std::vector<int16_t> outputs;
+ int16_t production_hint;
+
+ int32_t cnt_built;
+ int32_t cnt_under_construction;
+
+ int32_t total_count() const { return cnt_built + cnt_under_construction; }
+ bool buildable(Widelands::Player& player) {
+ return is_buildable && player.is_building_type_allowed(id);
+ }
};
struct ProductionSiteObserver {
- Widelands::ProductionSite * site;
- int32_t builttime;
- uint8_t statszero;
- BuildingObserver * bo;
+ Widelands::ProductionSite* site;
+ int32_t builttime;
+ uint8_t statszero;
+ BuildingObserver* bo;
};
struct MilitarySiteObserver {
- Widelands::MilitarySite * site;
- BuildingObserver * bo;
- uint8_t checks;
+ Widelands::MilitarySite* site;
+ BuildingObserver* bo;
+ uint8_t checks;
};
struct WareObserver {
- uint8_t producers;
- uint8_t consumers;
- uint8_t preciousness;
+ uint8_t producers;
+ uint8_t consumers;
+ uint8_t preciousness;
};
#endif
=== modified file 'src/ai/ai_hints.cc'
--- src/ai/ai_hints.cc 2012-02-15 21:25:34 +0000
+++ src/ai/ai_hints.cc 2013-05-18 05:56:27 +0000
@@ -23,29 +23,26 @@
#include <cstring>
-
-BuildingHints::~BuildingHints ()
-{
- free(renews_map_resource);
- free(mines);
+BuildingHints::~BuildingHints() {
+ free(renews_map_resource);
+ free(mines);
}
-BuildingHints::BuildingHints (Section * const section) :
- renews_map_resource(0),
- mines (0),
- basic (section ? section->get_bool("is_basic") : false),
- build_material (section ? section->get_bool("build_material") : true),
- trunkproducer (section ? section->get_bool("trunkproducer") : false),
- stoneproducer (section ? section->get_bool("stoneproducer") : false),
- needs_water (section ? section->get_bool("needs_water") : false),
- recruitment (section ? section->get_bool("recruitment") : false),
- space_consumer (section ? section->get_bool("space_consumer") : false),
- mines_percent (section ? section->get_int ("mines_percent", 100) : 0)
-{
- if (section) {
- if (char const * const s = section->get_string("renews_map_resource"))
- renews_map_resource = strdup(s);
- if (char const * const s = section->get_string("mines"))
- mines = strdup(s);
- }
+BuildingHints::BuildingHints(Section* const section)
+ : renews_map_resource(0),
+ mines(0),
+ basic(section ? section->get_bool("is_basic") : false),
+ build_material(section ? section->get_bool("build_material") : true),
+ trunkproducer(section ? section->get_bool("trunkproducer") : false),
+ stoneproducer(section ? section->get_bool("stoneproducer") : false),
+ needs_water(section ? section->get_bool("needs_water") : false),
+ recruitment(section ? section->get_bool("recruitment") : false),
+ space_consumer(section ? section->get_bool("space_consumer") : false),
+ mines_percent(section ? section->get_int("mines_percent", 100) : 0) {
+ if (section) {
+ if (char const* const s = section->get_string("renews_map_resource"))
+ renews_map_resource = strdup(s);
+ if (char const* const s = section->get_string("mines"))
+ mines = strdup(s);
+ }
}
=== modified file 'src/ai/ai_hints.h'
--- src/ai/ai_hints.h 2012-02-15 21:25:34 +0000
+++ src/ai/ai_hints.h 2013-05-18 05:56:27 +0000
@@ -30,40 +30,40 @@
/// buildings conf file. It is used to tell the computer player about the
/// special properties of a building.
struct BuildingHints : boost::noncopyable {
- BuildingHints (Section *);
- ~BuildingHints();
-
- char const * get_renews_map_resource() const {return renews_map_resource;}
-
- char const * get_mines () const {return mines;}
-
- bool is_basic () const {return basic;}
-
- bool prod_build_material () const {return build_material;}
-
- bool is_trunkproducer () const {return trunkproducer;}
-
- bool is_stoneproducer () const {return stoneproducer;}
-
- bool get_needs_water () const {return needs_water;}
-
- bool for_recruitment () const {return recruitment;}
-
- bool is_space_consumer () const {return space_consumer;}
-
- uint8_t get_mines_percent () const {return mines_percent;}
-
-private:
- char * renews_map_resource;
- char * mines;
- bool basic;
- bool build_material; // whether the building produces build material
- bool trunkproducer;
- bool stoneproducer;
- bool needs_water;
- bool recruitment; // whether building recruits special workers
- bool space_consumer;
- uint8_t mines_percent;
+ BuildingHints(Section*);
+ ~BuildingHints();
+
+ char const* get_renews_map_resource() const { return renews_map_resource; }
+
+ char const* get_mines() const { return mines; }
+
+ bool is_basic() const { return basic; }
+
+ bool prod_build_material() const { return build_material; }
+
+ bool is_trunkproducer() const { return trunkproducer; }
+
+ bool is_stoneproducer() const { return stoneproducer; }
+
+ bool get_needs_water() const { return needs_water; }
+
+ bool for_recruitment() const { return recruitment; }
+
+ bool is_space_consumer() const { return space_consumer; }
+
+ uint8_t get_mines_percent() const { return mines_percent; }
+
+ private:
+ char* renews_map_resource;
+ char* mines;
+ bool basic;
+ bool build_material; // whether the building produces build material
+ bool trunkproducer;
+ bool stoneproducer;
+ bool needs_water;
+ bool recruitment; // whether building recruits special workers
+ bool space_consumer;
+ uint8_t mines_percent;
};
#endif
=== modified file 'src/ai/defaultai.cc'
--- src/ai/defaultai.cc 2013-03-05 21:23:00 +0000
+++ src/ai/defaultai.cc 2013-05-18 05:56:27 +0000
@@ -58,337 +58,320 @@
DefaultAI::DefensiveImpl DefaultAI::defensiveImpl;
/// Constructor of DefaultAI
-DefaultAI::DefaultAI(Game & ggame, Player_Number const pid, uint8_t const t) :
- Computer_Player (ggame, pid),
- type (t),
- m_buildable_changed (true),
- m_mineable_changed (true),
- player (0),
- tribe (0),
- total_constructionsites (0),
- next_road_due (2000),
- next_stats_update_due (30000),
- next_construction_due (1000),
- next_productionsite_check_due(0),
- next_mine_check_due (0),
- next_militarysite_check_due (0),
- next_attack_consideration_due(300000),
- inhibit_road_building (0),
- time_of_last_construction (0),
- numof_warehouses (0)
-{}
+DefaultAI::DefaultAI(Game& ggame, Player_Number const pid, uint8_t const t)
+ : Computer_Player(ggame, pid),
+ type(t),
+ m_buildable_changed(true),
+ m_mineable_changed(true),
+ player(0),
+ tribe(0),
+ total_constructionsites(0),
+ next_road_due(2000),
+ next_stats_update_due(30000),
+ next_construction_due(1000),
+ next_productionsite_check_due(0),
+ next_mine_check_due(0),
+ next_militarysite_check_due(0),
+ next_attack_consideration_due(300000),
+ inhibit_road_building(0),
+ time_of_last_construction(0),
+ numof_warehouses(0) {}
-DefaultAI::~DefaultAI()
-{
- while (not buildable_fields.empty()) {
- delete buildable_fields.back();
- buildable_fields.pop_back();
- }
- while (not mineable_fields.empty()) {
- delete mineable_fields.back();
- mineable_fields.pop_back();
- }
- while (not economies.empty()) {
- delete economies.back();
- economies.pop_back();
- }
+DefaultAI::~DefaultAI() {
+ while (not buildable_fields.empty()) {
+ delete buildable_fields.back();
+ buildable_fields.pop_back();
+ }
+ while (not mineable_fields.empty()) {
+ delete mineable_fields.back();
+ mineable_fields.pop_back();
+ }
+ while (not economies.empty()) {
+ delete economies.back();
+ economies.pop_back();
+ }
}
-
/**
* Main loop of computer player "defaultAI"
*
* General behaviour is defined here.
*/
-void DefaultAI::think ()
-{
- if (tribe == 0)
- late_initialization ();
-
- const int32_t gametime = game().get_gametime();
-
- if (m_buildable_changed) {
- // update statistics about buildable fields
- update_all_buildable_fields(gametime);
- }
- if (m_mineable_changed) {
- // do the same for mineable fields
- update_all_mineable_fields(gametime);
- }
- m_buildable_changed = false;
- m_mineable_changed = false;
-
- // if there are more than one economy try to connect them with a road.
- if (next_road_due <= gametime) {
- next_road_due = gametime + 1000;
- if (construct_roads (gametime)) {
- m_buildable_changed = true;
- m_mineable_changed = true;
- return;
- }
- } else
- // only go on, after defaultAI tried to connect all economies.
- return;
-
- // NOTE Because of the check above, the following parts of think() are used
- // NOTE only once every second at maximum. This increases performance and as
- // NOTE human players can not even react that fast, it should not be a
- // NOTE disadvantage for the defaultAI.
-
- // This must be checked every time as changes of bobs in AI area aren't
- // handled by the AI itself.
- update_all_not_buildable_fields();
-
- // IF defaultAI is AGGRESSIVE - we definitely should consider to attack as
- // often as possible.
- if (type == AGGRESSIVE)
- if (next_attack_consideration_due <= gametime)
- consider_attack(gametime);
-
- // check if anything in the economies changed.
- // This needs to be done before new buildings are placed, to ensure that no
- // empty economy is left.
- if (check_economies())
- return;
-
- // Before thinking about a new construction, update current stats, to have
- // a better view on current economy.
- if (next_stats_update_due <= gametime)
- update_productionsite_stats(gametime);
-
- // Now try to build something if possible
- if (next_construction_due <= gametime) {
- next_construction_due = gametime + 2000;
- if (construct_building(gametime)) {
- time_of_last_construction = gametime;
- return;
- }
- }
-
- // verify that our production sites are doing well
- if (check_productionsites(gametime))
- return;
-
- // Check the mines and consider upgrading or destroying one
- if (check_mines(gametime))
- return;
-
- // consider whether a change of the soldier capacity of some militarysites
- // would make sense.
- if (check_militarysites(gametime))
- return;
-
- // Finally consider military actions if defaultAI type is Aggressive or
- // Normal.
- if (!(type == DEFENSIVE))
- if (next_attack_consideration_due <= gametime)
- consider_attack(gametime);
-
- // improve existing roads!
- // This sounds important, but actually is not as important as the other
- // actions are. Reasons are the following:
- // * The "donkey feature" made economies more stable, even with stupid
- // roads.
- // * If defaultAI builds too much roads, it will waste good building
- // space.
- if (improve_roads(gametime)) {
- m_buildable_changed = true;
- m_mineable_changed = true;
- inhibit_road_building = gametime + 2500;
- return;
- }
+void DefaultAI::think() {
+ if (tribe == 0)
+ late_initialization();
+
+ const int32_t gametime = game().get_gametime();
+
+ if (m_buildable_changed) {
+ // update statistics about buildable fields
+ update_all_buildable_fields(gametime);
+ }
+ if (m_mineable_changed) {
+ // do the same for mineable fields
+ update_all_mineable_fields(gametime);
+ }
+ m_buildable_changed = false;
+ m_mineable_changed = false;
+
+ // if there are more than one economy try to connect them with a road.
+ if (next_road_due <= gametime) {
+ next_road_due = gametime + 1000;
+ if (construct_roads(gametime)) {
+ m_buildable_changed = true;
+ m_mineable_changed = true;
+ return;
+ }
+ } else
+ // only go on, after defaultAI tried to connect all economies.
+ return;
+
+ // NOTE Because of the check above, the following parts of think() are used
+ // NOTE only once every second at maximum. This increases performance and as
+ // NOTE human players can not even react that fast, it should not be a
+ // NOTE disadvantage for the defaultAI.
+
+ // This must be checked every time as changes of bobs in AI area aren't
+ // handled by the AI itself.
+ update_all_not_buildable_fields();
+
+ // IF defaultAI is AGGRESSIVE - we definitely should consider to attack as
+ // often as possible.
+ if (type == AGGRESSIVE)
+ if (next_attack_consideration_due <= gametime)
+ consider_attack(gametime);
+
+ // check if anything in the economies changed.
+ // This needs to be done before new buildings are placed, to ensure that no
+ // empty economy is left.
+ if (check_economies())
+ return;
+
+ // Before thinking about a new construction, update current stats, to have
+ // a better view on current economy.
+ if (next_stats_update_due <= gametime)
+ update_productionsite_stats(gametime);
+
+ // Now try to build something if possible
+ if (next_construction_due <= gametime) {
+ next_construction_due = gametime + 2000;
+ if (construct_building(gametime)) {
+ time_of_last_construction = gametime;
+ return;
+ }
+ }
+
+ // verify that our production sites are doing well
+ if (check_productionsites(gametime))
+ return;
+
+ // Check the mines and consider upgrading or destroying one
+ if (check_mines(gametime))
+ return;
+
+ // consider whether a change of the soldier capacity of some militarysites
+ // would make sense.
+ if (check_militarysites(gametime))
+ return;
+
+ // Finally consider military actions if defaultAI type is Aggressive or
+ // Normal.
+ if (!(type == DEFENSIVE))
+ if (next_attack_consideration_due <= gametime)
+ consider_attack(gametime);
+
+ // improve existing roads!
+ // This sounds important, but actually is not as important as the other
+ // actions are. Reasons are the following:
+ // * The "donkey feature" made economies more stable, even with stupid
+ // roads.
+ // * If defaultAI builds too much roads, it will waste good building
+ // space.
+ if (improve_roads(gametime)) {
+ m_buildable_changed = true;
+ m_mineable_changed = true;
+ inhibit_road_building = gametime + 2500;
+ return;
+ }
}
/// called by Widelands game engine when an immovable changed
-void DefaultAI::receive(const NoteImmovable & note)
-{
- if (note.lg == LOSE)
- lose_immovable(*note.pi);
- else
- gain_immovable(*note.pi);
+void DefaultAI::receive(const NoteImmovable& note) {
+ if (note.lg == LOSE)
+ lose_immovable(*note.pi);
+ else
+ gain_immovable(*note.pi);
}
/// called by Widelands game engine when a field changed
-void DefaultAI::receive(const NoteFieldPossession & note)
-{
- if (note.lg == GAIN)
- unusable_fields.push_back(note.fc);
+void DefaultAI::receive(const NoteFieldPossession& note) {
+ if (note.lg == GAIN)
+ unusable_fields.push_back(note.fc);
}
-
/**
* Cares for all variables not initialised during construction
*
* When DefaultAI is constructed, some information is not yet available (e.g.
* world), so this is done after complete loading of the map.
*/
-void DefaultAI::late_initialization ()
-{
- player = game().get_player(player_number());
- NoteReceiver<NoteImmovable>::connect(*player);
- NoteReceiver<NoteFieldPossession>::connect(*player);
- tribe = &player->tribe();
-
- log ("ComputerPlayer(%d): initializing (%u)\n", player_number(), type);
-
- Ware_Index const nr_wares = tribe->get_nrwares();
- wares.resize(nr_wares.value());
- for (Ware_Index i = Ware_Index::First(); i < nr_wares; ++i) {
- wares.at(i).producers = 0;
- wares.at(i).consumers = 0;
- wares.at(i).preciousness = tribe->get_ware_descr(i)->preciousness();
- }
-
- // collect information about the different buildings our tribe can construct
- Building_Index const nr_buildings = tribe->get_nrbuildings();
- const World & world = game().map().world();
- for (Building_Index i = Building_Index::First(); i < nr_buildings; ++i) {
- const Building_Descr & bld = *tribe->get_building_descr(i);
- const std::string & building_name = bld.name();
- const BuildingHints & bh = bld.hints();
-
- buildings.resize (buildings.size() + 1);
-
- BuildingObserver & bo = buildings.back();
- bo.name = building_name.c_str();
- bo.id = i;
- bo.desc = &bld;
- bo.type = BuildingObserver::BORING;
- bo.cnt_built = 0;
- bo.cnt_under_construction = 0;
- bo.production_hint = -1;
- bo.current_stats = 100;
- bo.unoccupied = false;
-
- bo.is_basic = false;
-
- bo.is_buildable = bld.is_buildable();
-
- bo.need_trees = bh.is_trunkproducer();
- bo.need_stones = bh.is_stoneproducer();
- bo.need_water = bh.get_needs_water();
- bo.recruitment = bh.for_recruitment();
- bo.space_consumer = bh.is_space_consumer();
-
- if (char const * const s = bh.get_renews_map_resource())
- bo.production_hint = tribe->safe_ware_index(s).value();
-
- // Read all interesting data from ware producing buildings
- if (typeid(bld) == typeid(ProductionSite_Descr)) {
- const ProductionSite_Descr & prod =
- ref_cast<ProductionSite_Descr const, Building_Descr const>(bld);
-
- bo.type =
- bld.get_ismine() ? BuildingObserver::MINE :
- BuildingObserver::PRODUCTIONSITE;
-
- container_iterate_const(Ware_Types, prod.inputs(), j)
- bo.inputs.push_back(j.current->first.value());
-
- container_iterate_const
- (ProductionSite_Descr::Output, prod.output_ware_types(), j)
- bo.outputs.push_back(j.current-> value());
-
- if (bo.type == BuildingObserver::MINE) {
- // get the resource needed by the mine
- if (char const * const s = bh.get_mines())
- bo.mines = world.get_resource(s);
- bo.mines_percent = bh.get_mines_percent();
- }
-
- bo.is_basic = bh.is_basic();
- bo.prod_build_material = bh.prod_build_material();
-
- continue;
- }
-
- if (typeid(bld) == typeid(MilitarySite_Descr)) {
- bo.type = BuildingObserver::MILITARYSITE;
- continue;
- }
-
- if (typeid(bld) == typeid(Warehouse_Descr)) {
- bo.type = BuildingObserver::WAREHOUSE;
- continue;
- }
-
- if (typeid(bld) == typeid(TrainingSite_Descr)) {
- bo.type = BuildingObserver::TRAININGSITE;
- continue;
- }
-
- if (typeid(bld) == typeid(ConstructionSite_Descr)) {
- bo.type = BuildingObserver::CONSTRUCTIONSITE;
- continue;
- }
- }
-
- total_constructionsites = 0;
- next_construction_due = 0;
- next_road_due = 1000;
- next_productionsite_check_due = 0;
- inhibit_road_building = 0;
-
- // Add all fields that we own
- Map & map = game().map();
- std::set<OPtr<PlayerImmovable> > found_immovables;
-
- for (Y_Coordinate y = 0; y < map.get_height(); ++y) {
- for (X_Coordinate x = 0; x < map.get_width(); ++x) {
- FCoords f = map.get_fcoords(Coords(x, y));
-
- if (f.field->get_owned_by() != player_number())
- continue;
-
- unusable_fields.push_back (f);
-
- if (upcast(PlayerImmovable, imm, f.field->get_immovable()))
- // Guard by a set - immovables might be on several nodes at once.
- if (&imm->owner() == player and not found_immovables.count(imm)) {
- found_immovables.insert(imm);
- gain_immovable(*imm);
- }
- }
- }
+void DefaultAI::late_initialization() {
+ player = game().get_player(player_number());
+ NoteReceiver<NoteImmovable>::connect(*player);
+ NoteReceiver<NoteFieldPossession>::connect(*player);
+ tribe = &player->tribe();
+
+ log("ComputerPlayer(%d): initializing (%u)\n", player_number(), type);
+
+ Ware_Index const nr_wares = tribe->get_nrwares();
+ wares.resize(nr_wares.value());
+ for (Ware_Index i = Ware_Index::First(); i < nr_wares; ++i) {
+ wares.at(i).producers = 0;
+ wares.at(i).consumers = 0;
+ wares.at(i).preciousness = tribe->get_ware_descr(i)->preciousness();
+ }
+
+ // collect information about the different buildings our tribe can construct
+ Building_Index const nr_buildings = tribe->get_nrbuildings();
+ const World& world = game().map().world();
+ for (Building_Index i = Building_Index::First(); i < nr_buildings; ++i) {
+ const Building_Descr& bld = *tribe->get_building_descr(i);
+ const std::string& building_name = bld.name();
+ const BuildingHints& bh = bld.hints();
+
+ buildings.resize(buildings.size() + 1);
+
+ BuildingObserver& bo = buildings.back();
+ bo.name = building_name.c_str();
+ bo.id = i;
+ bo.desc = &bld;
+ bo.type = BuildingObserver::BORING;
+ bo.cnt_built = 0;
+ bo.cnt_under_construction = 0;
+ bo.production_hint = -1;
+ bo.current_stats = 100;
+ bo.unoccupied = false;
+
+ bo.is_basic = false;
+
+ bo.is_buildable = bld.is_buildable();
+
+ bo.need_trees = bh.is_trunkproducer();
+ bo.need_stones = bh.is_stoneproducer();
+ bo.need_water = bh.get_needs_water();
+ bo.recruitment = bh.for_recruitment();
+ bo.space_consumer = bh.is_space_consumer();
+
+ if (char const* const s = bh.get_renews_map_resource())
+ bo.production_hint = tribe->safe_ware_index(s).value();
+
+ // Read all interesting data from ware producing buildings
+ if (typeid(bld) == typeid(ProductionSite_Descr)) {
+ const ProductionSite_Descr& prod =
+ ref_cast<ProductionSite_Descr const, Building_Descr const>(bld);
+
+ bo.type = bld.get_ismine() ? BuildingObserver::MINE : BuildingObserver::PRODUCTIONSITE;
+
+ container_iterate_const(Ware_Types, prod.inputs(), j)
+ bo.inputs.push_back(j.current->first.value());
+
+ container_iterate_const(ProductionSite_Descr::Output, prod.output_ware_types(), j)
+ bo.outputs.push_back(j.current->value());
+
+ if (bo.type == BuildingObserver::MINE) {
+ // get the resource needed by the mine
+ if (char const* const s = bh.get_mines())
+ bo.mines = world.get_resource(s);
+ bo.mines_percent = bh.get_mines_percent();
+ }
+
+ bo.is_basic = bh.is_basic();
+ bo.prod_build_material = bh.prod_build_material();
+
+ continue;
+ }
+
+ if (typeid(bld) == typeid(MilitarySite_Descr)) {
+ bo.type = BuildingObserver::MILITARYSITE;
+ continue;
+ }
+
+ if (typeid(bld) == typeid(Warehouse_Descr)) {
+ bo.type = BuildingObserver::WAREHOUSE;
+ continue;
+ }
+
+ if (typeid(bld) == typeid(TrainingSite_Descr)) {
+ bo.type = BuildingObserver::TRAININGSITE;
+ continue;
+ }
+
+ if (typeid(bld) == typeid(ConstructionSite_Descr)) {
+ bo.type = BuildingObserver::CONSTRUCTIONSITE;
+ continue;
+ }
+ }
+
+ total_constructionsites = 0;
+ next_construction_due = 0;
+ next_road_due = 1000;
+ next_productionsite_check_due = 0;
+ inhibit_road_building = 0;
+
+ // Add all fields that we own
+ Map& map = game().map();
+ std::set<OPtr<PlayerImmovable> > found_immovables;
+
+ for (Y_Coordinate y = 0; y < map.get_height(); ++y) {
+ for (X_Coordinate x = 0; x < map.get_width(); ++x) {
+ FCoords f = map.get_fcoords(Coords(x, y));
+
+ if (f.field->get_owned_by() != player_number())
+ continue;
+
+ unusable_fields.push_back(f);
+
+ if (upcast(PlayerImmovable, imm, f.field->get_immovable()))
+ // Guard by a set - immovables might be on several nodes at once.
+ if (&imm->owner() == player and not found_immovables.count(imm)) {
+ found_immovables.insert(imm);
+ gain_immovable(*imm);
+ }
+ }
+ }
}
-
/**
* Checks ALL available buildable fields.
*
* this shouldn't be used often, as it might hang the game for some 100
* milliseconds if the area the computer owns is big.
*/
-void DefaultAI::update_all_buildable_fields(const int32_t gametime)
-{
- while
- (not buildable_fields.empty()
- and
- buildable_fields.front()->next_update_due <= gametime)
- {
- BuildableField & bf = *buildable_fields.front();
-
- // check whether we lost ownership of the node
- if (bf.coords.field->get_owned_by() != player_number()) {
- delete &bf;
- buildable_fields.pop_front();
- continue;
- }
-
- // check whether we can still construct regular buildings on the node
- if ((player->get_buildcaps(bf.coords) & BUILDCAPS_SIZEMASK) == 0) {
- unusable_fields.push_back (bf.coords);
- delete &bf;
- buildable_fields.pop_front();
- continue;
- }
-
- update_buildable_field (bf);
- bf.next_update_due = gametime + FIELD_UPDATE_INTERVAL;
-
- buildable_fields.push_back (&bf);
- buildable_fields.pop_front ();
- }
+void DefaultAI::update_all_buildable_fields(const int32_t gametime) {
+ while (not buildable_fields.empty() and buildable_fields.front()->next_update_due <= gametime) {
+ BuildableField& bf = *buildable_fields.front();
+
+ // check whether we lost ownership of the node
+ if (bf.coords.field->get_owned_by() != player_number()) {
+ delete &bf;
+ buildable_fields.pop_front();
+ continue;
+ }
+
+ // check whether we can still construct regular buildings on the node
+ if ((player->get_buildcaps(bf.coords) & BUILDCAPS_SIZEMASK) == 0) {
+ unusable_fields.push_back(bf.coords);
+ delete &bf;
+ buildable_fields.pop_front();
+ continue;
+ }
+
+ update_buildable_field(bf);
+ bf.next_update_due = gametime + FIELD_UPDATE_INTERVAL;
+
+ buildable_fields.push_back(&bf);
+ buildable_fields.pop_front();
+ }
}
/**
@@ -397,37 +380,32 @@
* this shouldn't be used often, as it might hang the game for some 100
* milliseconds if the area the computer owns is big.
*/
-void DefaultAI::update_all_mineable_fields(const int32_t gametime)
-{
- while
- (not mineable_fields.empty()
- and
- mineable_fields.front()->next_update_due <= gametime)
- {
- MineableField * mf = mineable_fields.front();
-
- // check whether we lost ownership of the node
- if (mf->coords.field->get_owned_by() != player_number()) {
- delete mf;
- mineable_fields.pop_front();
- continue;
- }
-
- // check whether we can still construct regular buildings on the node
- if ((player->get_buildcaps(mf->coords) & BUILDCAPS_MINE) == 0) {
- unusable_fields.push_back (mf->coords);
- delete mf;
-
- mineable_fields.pop_front();
- continue;
- }
-
- update_mineable_field (*mf);
- mf->next_update_due = gametime + FIELD_UPDATE_INTERVAL;
-
- mineable_fields.push_back (mf);
- mineable_fields.pop_front ();
- }
+void DefaultAI::update_all_mineable_fields(const int32_t gametime) {
+ while (not mineable_fields.empty() and mineable_fields.front()->next_update_due <= gametime) {
+ MineableField* mf = mineable_fields.front();
+
+ // check whether we lost ownership of the node
+ if (mf->coords.field->get_owned_by() != player_number()) {
+ delete mf;
+ mineable_fields.pop_front();
+ continue;
+ }
+
+ // check whether we can still construct regular buildings on the node
+ if ((player->get_buildcaps(mf->coords) & BUILDCAPS_MINE) == 0) {
+ unusable_fields.push_back(mf->coords);
+ delete mf;
+
+ mineable_fields.pop_front();
+ continue;
+ }
+
+ update_mineable_field(*mf);
+ mf->next_update_due = gametime + FIELD_UPDATE_INTERVAL;
+
+ mineable_fields.push_back(mf);
+ mineable_fields.pop_front();
+ }
}
/**
@@ -435,287 +413,247 @@
*
* milliseconds if the area the computer owns is big.
*/
-void DefaultAI::update_all_not_buildable_fields()
-{
- int32_t const pn = player_number();
- uint32_t maxchecks = unusable_fields.size();
- if (maxchecks > 50)
- maxchecks = 50;
-
- for (uint32_t i = 0; i < maxchecks; ++i) {
- // check whether we lost ownership of the node
- if (unusable_fields.front().field->get_owned_by() != pn) {
- unusable_fields.pop_front();
- continue;
- }
-
- // check whether building capabilities have improved
- if (player->get_buildcaps(unusable_fields.front()) & BUILDCAPS_SIZEMASK)
- {
-
- buildable_fields.push_back
- (new BuildableField(unusable_fields.front()));
- unusable_fields.pop_front();
-
- update_buildable_field (*buildable_fields.back());
- continue;
- }
-
- if (player->get_buildcaps(unusable_fields.front()) & BUILDCAPS_MINE) {
-
- mineable_fields.push_back
- (new MineableField(unusable_fields.front()));
- unusable_fields.pop_front();
-
- update_mineable_field (*mineable_fields.back());
- continue;
- }
-
- unusable_fields.push_back(unusable_fields.front());
- unusable_fields.pop_front();
- }
+void DefaultAI::update_all_not_buildable_fields() {
+ int32_t const pn = player_number();
+ uint32_t maxchecks = unusable_fields.size();
+ if (maxchecks > 50)
+ maxchecks = 50;
+
+ for (uint32_t i = 0; i < maxchecks; ++i) {
+ // check whether we lost ownership of the node
+ if (unusable_fields.front().field->get_owned_by() != pn) {
+ unusable_fields.pop_front();
+ continue;
+ }
+
+ // check whether building capabilities have improved
+ if (player->get_buildcaps(unusable_fields.front()) & BUILDCAPS_SIZEMASK) {
+
+ buildable_fields.push_back(new BuildableField(unusable_fields.front()));
+ unusable_fields.pop_front();
+
+ update_buildable_field(*buildable_fields.back());
+ continue;
+ }
+
+ if (player->get_buildcaps(unusable_fields.front()) & BUILDCAPS_MINE) {
+
+ mineable_fields.push_back(new MineableField(unusable_fields.front()));
+ unusable_fields.pop_front();
+
+ update_mineable_field(*mineable_fields.back());
+ continue;
+ }
+
+ unusable_fields.push_back(unusable_fields.front());
+ unusable_fields.pop_front();
+ }
}
-
/// Updates one buildable field
-void DefaultAI::update_buildable_field
- (BuildableField & field, uint16_t range, bool military)
-{
- // look if there is any unowned land nearby
- Map & map = game().map();
- FindNodeUnowned find_unowned(player, game());
- Player_Number const pn = player->player_number();
-
- field.unowned_land_nearby =
- map.find_fields(Area<FCoords>(field.coords, range), 0, find_unowned);
-
- // collect information about resources in the area
- std::vector<ImmovableFound> immovables;
-
- // Search in a radius of range
- map.find_immovables (Area<FCoords>(field.coords, range), &immovables);
-
- // Is this a general update or just for military consideration
- // (second is used in check_militarysites)
- if (!military) {
- int32_t const tree_attr = Map_Object_Descr::get_attribute_id("tree");
- int32_t const stone_attr = Map_Object_Descr::get_attribute_id("stone");
-
- field.reachable = false;
- field.preferred = false;
- field.avoid_military = false;
- field.enemy_nearby = false;
-
- field.military_influence = 0;
- field.trees_nearby = 0;
- field.stones_nearby = 0;
- field.space_consumers_nearby = 0;
- field.producers_nearby.clear();
- field.producers_nearby.resize(wares.size());
- field.consumers_nearby.clear();
- field.consumers_nearby.resize(wares.size());
- std::vector<Coords> water_list;
- FindNodeWater find_water;
- map.find_fields(Area<FCoords>(field.coords, 4), &water_list, find_water);
- field.water_nearby = water_list.size();
-
- FCoords fse;
- map.get_neighbour (field.coords, WALK_SE, &fse);
-
- if (BaseImmovable const * const imm = fse.field->get_immovable())
- if
- (dynamic_cast<Flag const *>(imm)
- or
- (dynamic_cast<Road const *>(imm)
- &&
- (fse.field->nodecaps() & BUILDCAPS_FLAG)))
- field.preferred = true;
-
- for (uint32_t i = 0; i < immovables.size(); ++i) {
- const BaseImmovable & base_immovable = *immovables.at(i).object;
- if (dynamic_cast<const Flag *>(&base_immovable))
- field.reachable = true;
- if (upcast(PlayerImmovable const, player_immovable, &base_immovable))
- // TODO Only continue; if this is an opposing site
- // TODO allied sites should be counted for military influence
- if (player_immovable->owner().player_number() != pn) {
- if (player->is_hostile(player_immovable->owner()))
- field.enemy_nearby = true;
- continue;
- }
-
- if (upcast(Building const, building, &base_immovable)) {
-
- if (upcast(ConstructionSite const, constructionsite, building)) {
- const Building_Descr & target_descr =
- constructionsite->building();
-
- if
- (upcast
- (MilitarySite_Descr const, target_ms_d, &target_descr))
- {
- const int32_t v =
- target_ms_d->get_conquers()
- -
- map.calc_distance(field.coords, immovables.at(i).coords);
-
- if (0 < v) {
- field.military_influence += v * (v + 2) * 6;
- field.avoid_military = true;
- }
- }
-
- if (dynamic_cast<ProductionSite_Descr const *>(&target_descr))
- consider_productionsite_influence
- (field,
- immovables.at(i).coords,
- get_building_observer(constructionsite->name().c_str()));
- }
-
- if (upcast(MilitarySite const, militarysite, building)) {
- const int32_t v =
- militarysite->get_conquers()
- -
- map.calc_distance(field.coords, immovables.at(i).coords);
-
- if (v > 0)
- field.military_influence +=
- v * v * militarysite->soldierCapacity();
- }
-
- if (dynamic_cast<const ProductionSite *>(building))
- consider_productionsite_influence
- (field,
- immovables.at(i).coords,
- get_building_observer(building->name().c_str()));
-
- continue;
- }
-
- if (immovables.at(i).object->has_attribute(tree_attr))
- ++field.trees_nearby;
-
- if (immovables.at(i).object->has_attribute(stone_attr))
- ++field.stones_nearby;
- }
- } else { // the small update just for military consideration
- for (uint32_t i = 0; i < immovables.size(); ++i) {
- const BaseImmovable & base_immovable = *immovables.at(i).object;
- if (upcast(Building const, building, &base_immovable)) {
- if (upcast(ConstructionSite const, constructionsite, building)) {
- const Building_Descr & target_descr =
- constructionsite->building();
-
- if
- (upcast
- (MilitarySite_Descr const, target_ms_d, &target_descr))
- {
- const int32_t v =
- target_ms_d->get_conquers()
- -
- map.calc_distance(field.coords, immovables.at(i).coords);
-
- if (0 < v) {
- field.military_influence += v * (v + 2) * 6;
- field.avoid_military = true;
- }
- }
- }
- if (upcast(MilitarySite const, militarysite, building)) {
- const int32_t v =
- militarysite->get_conquers()
- -
- map.calc_distance(field.coords, immovables.at(i).coords);
-
- if (v > 0)
- field.military_influence +=
- v * v * militarysite->soldierCapacity();
- }
- }
- }
- }
+void DefaultAI::update_buildable_field(BuildableField& field, uint16_t range, bool military) {
+ // look if there is any unowned land nearby
+ Map& map = game().map();
+ FindNodeUnowned find_unowned(player, game());
+ Player_Number const pn = player->player_number();
+
+ field.unowned_land_nearby = map.find_fields(Area<FCoords>(field.coords, range), 0, find_unowned);
+
+ // collect information about resources in the area
+ std::vector<ImmovableFound> immovables;
+
+ // Search in a radius of range
+ map.find_immovables(Area<FCoords>(field.coords, range), &immovables);
+
+ // Is this a general update or just for military consideration
+ // (second is used in check_militarysites)
+ if (!military) {
+ int32_t const tree_attr = Map_Object_Descr::get_attribute_id("tree");
+ int32_t const stone_attr = Map_Object_Descr::get_attribute_id("stone");
+
+ field.reachable = false;
+ field.preferred = false;
+ field.avoid_military = false;
+ field.enemy_nearby = false;
+
+ field.military_influence = 0;
+ field.trees_nearby = 0;
+ field.stones_nearby = 0;
+ field.space_consumers_nearby = 0;
+ field.producers_nearby.clear();
+ field.producers_nearby.resize(wares.size());
+ field.consumers_nearby.clear();
+ field.consumers_nearby.resize(wares.size());
+ std::vector<Coords> water_list;
+ FindNodeWater find_water;
+ map.find_fields(Area<FCoords>(field.coords, 4), &water_list, find_water);
+ field.water_nearby = water_list.size();
+
+ FCoords fse;
+ map.get_neighbour(field.coords, WALK_SE, &fse);
+
+ if (BaseImmovable const* const imm = fse.field->get_immovable())
+ if (dynamic_cast<Flag const*>(imm)
+ or(dynamic_cast<Road const*>(imm) && (fse.field->nodecaps() & BUILDCAPS_FLAG)))
+ field.preferred = true;
+
+ for (uint32_t i = 0; i < immovables.size(); ++i) {
+ const BaseImmovable& base_immovable = *immovables.at(i).object;
+ if (dynamic_cast<const Flag*>(&base_immovable))
+ field.reachable = true;
+ if (upcast(PlayerImmovable const, player_immovable, &base_immovable))
+ // TODO Only continue; if this is an opposing site
+ // TODO allied sites should be counted for military influence
+ if (player_immovable->owner().player_number() != pn) {
+ if (player->is_hostile(player_immovable->owner()))
+ field.enemy_nearby = true;
+ continue;
+ }
+
+ if (upcast(Building const, building, &base_immovable)) {
+
+ if (upcast(ConstructionSite const, constructionsite, building)) {
+ const Building_Descr& target_descr = constructionsite->building();
+
+ if (upcast(MilitarySite_Descr const, target_ms_d, &target_descr)) {
+ const int32_t v = target_ms_d->get_conquers() -
+ map.calc_distance(field.coords, immovables.at(i).coords);
+
+ if (0 < v) {
+ field.military_influence += v * (v + 2) * 6;
+ field.avoid_military = true;
+ }
+ }
+
+ if (dynamic_cast<ProductionSite_Descr const*>(&target_descr))
+ consider_productionsite_influence(
+ field,
+ immovables.at(i).coords,
+ get_building_observer(constructionsite->name().c_str()));
+ }
+
+ if (upcast(MilitarySite const, militarysite, building)) {
+ const int32_t v = militarysite->get_conquers() -
+ map.calc_distance(field.coords, immovables.at(i).coords);
+
+ if (v > 0)
+ field.military_influence += v * v * militarysite->soldierCapacity();
+ }
+
+ if (dynamic_cast<const ProductionSite*>(building))
+ consider_productionsite_influence(
+ field, immovables.at(i).coords, get_building_observer(building->name().c_str()));
+
+ continue;
+ }
+
+ if (immovables.at(i).object->has_attribute(tree_attr))
+ ++field.trees_nearby;
+
+ if (immovables.at(i).object->has_attribute(stone_attr))
+ ++field.stones_nearby;
+ }
+ } else { // the small update just for military consideration
+ for (uint32_t i = 0; i < immovables.size(); ++i) {
+ const BaseImmovable& base_immovable = *immovables.at(i).object;
+ if (upcast(Building const, building, &base_immovable)) {
+ if (upcast(ConstructionSite const, constructionsite, building)) {
+ const Building_Descr& target_descr = constructionsite->building();
+
+ if (upcast(MilitarySite_Descr const, target_ms_d, &target_descr)) {
+ const int32_t v = target_ms_d->get_conquers() -
+ map.calc_distance(field.coords, immovables.at(i).coords);
+
+ if (0 < v) {
+ field.military_influence += v * (v + 2) * 6;
+ field.avoid_military = true;
+ }
+ }
+ }
+ if (upcast(MilitarySite const, militarysite, building)) {
+ const int32_t v = militarysite->get_conquers() -
+ map.calc_distance(field.coords, immovables.at(i).coords);
+
+ if (v > 0)
+ field.military_influence += v * v * militarysite->soldierCapacity();
+ }
+ }
+ }
+ }
}
/// Updates one mineable field
-void DefaultAI::update_mineable_field (MineableField & field)
-{
- // collect information about resources in the area
- std::vector<ImmovableFound> immovables;
- Map & map = game().map();
-
- map.find_immovables (Area<FCoords>(field.coords, 6), &immovables);
-
- field.reachable = false;
- field.preferred = false;
- field.mines_nearby = 1;
-
- FCoords fse;
- map.get_brn(field.coords, &fse);
-
- if (BaseImmovable const * const imm = fse.field->get_immovable())
- if
- (dynamic_cast<Flag const *>(imm)
- or
- (dynamic_cast<Road const *>(imm)
- &&
- (fse.field->nodecaps() & BUILDCAPS_FLAG)))
- field.preferred = true;
-
- container_iterate_const(std::vector<ImmovableFound>, immovables, i) {
- if (dynamic_cast<Flag const *>(i.current->object))
- field.reachable = true;
- else if (upcast(Building const, bld, i.current->object)) {
- if (bld->descr().get_ismine()) {
- ++field.mines_nearby;
- } else if (upcast(ConstructionSite const, cs, bld)) {
- if (cs->building().get_ismine())
- ++field.mines_nearby;
- }
- }
- }
+void DefaultAI::update_mineable_field(MineableField& field) {
+ // collect information about resources in the area
+ std::vector<ImmovableFound> immovables;
+ Map& map = game().map();
+
+ map.find_immovables(Area<FCoords>(field.coords, 6), &immovables);
+
+ field.reachable = false;
+ field.preferred = false;
+ field.mines_nearby = 1;
+
+ FCoords fse;
+ map.get_brn(field.coords, &fse);
+
+ if (BaseImmovable const* const imm = fse.field->get_immovable())
+ if (dynamic_cast<Flag const*>(imm)
+ or(dynamic_cast<Road const*>(imm) && (fse.field->nodecaps() & BUILDCAPS_FLAG)))
+ field.preferred = true;
+
+ container_iterate_const(std::vector<ImmovableFound>, immovables, i) {
+ if (dynamic_cast<Flag const*>(i.current->object))
+ field.reachable = true;
+ else if (upcast(Building const, bld, i.current->object)) {
+ if (bld->descr().get_ismine()) {
+ ++field.mines_nearby;
+ } else if (upcast(ConstructionSite const, cs, bld)) {
+ if (cs->building().get_ismine())
+ ++field.mines_nearby;
+ }
+ }
+ }
}
-
/// Updates the productionsites statistics needed for construction decision.
void DefaultAI::update_productionsite_stats(int32_t const gametime) {
- // Updating the stats every 20 seconds should be enough
- next_stats_update_due = gametime + 20000;
-
- // Reset statistics for all buildings
- for (uint32_t i = 0; i < buildings.size(); ++i) {
- if (buildings.at(i).cnt_built > 0)
- buildings.at(i).current_stats = 0;
- // If there are no buildings of that type set the current_stats to 100
- else
- buildings.at(i).current_stats = 100;
- buildings.at(i).unoccupied = false;
- }
-
- // Check all available productionsites
- for (uint32_t i = 0; i < productionsites.size(); ++i) {
- assert(productionsites.front().bo->cnt_built > 0);
-
- // Add statistics value
- productionsites.front().bo->current_stats +=
- productionsites.front().site->get_statistics_percent();
-
- // Check whether this building is completely occupied
- productionsites.front().bo->unoccupied |=
- !productionsites.front().site->can_start_working();
-
- // Now reorder the buildings
- productionsites.push_back(productionsites.front());
- productionsites.pop_front();
- }
-
- // Scale statistics down
- for (uint32_t i = 0; i < buildings.size(); ++i) {
- if (buildings.at(i).cnt_built > 0)
- buildings.at(i).current_stats /= buildings.at(i).cnt_built;
- }
+ // Updating the stats every 20 seconds should be enough
+ next_stats_update_due = gametime + 20000;
+
+ // Reset statistics for all buildings
+ for (uint32_t i = 0; i < buildings.size(); ++i) {
+ if (buildings.at(i).cnt_built > 0)
+ buildings.at(i).current_stats = 0;
+ // If there are no buildings of that type set the current_stats to 100
+ else
+ buildings.at(i).current_stats = 100;
+ buildings.at(i).unoccupied = false;
+ }
+
+ // Check all available productionsites
+ for (uint32_t i = 0; i < productionsites.size(); ++i) {
+ assert(productionsites.front().bo->cnt_built > 0);
+
+ // Add statistics value
+ productionsites.front().bo->current_stats +=
+ productionsites.front().site->get_statistics_percent();
+
+ // Check whether this building is completely occupied
+ productionsites.front().bo->unoccupied |= !productionsites.front().site->can_start_working();
+
+ // Now reorder the buildings
+ productionsites.push_back(productionsites.front());
+ productionsites.pop_front();
+ }
+
+ // Scale statistics down
+ for (uint32_t i = 0; i < buildings.size(); ++i) {
+ if (buildings.at(i).cnt_built > 0)
+ buildings.at(i).current_stats /= buildings.at(i).cnt_built;
+ }
}
-
/**
* constructs the most needed building
*
@@ -730,870 +668,814 @@
* that (should) depend on the initialisation type (Aggressive, Normal,
* Defensive)
*/
-bool DefaultAI::construct_building (int32_t) // (int32_t gametime)
-{
- // TODO make this smarter, easier and yet more effective
-
- // TODO implement handling of seafaring
-
- // Do not have too many constructionsites
- uint32_t producers = mines.size() + productionsites.size();
- bool onlymissing = false;
- if (total_constructionsites >= (2 + (producers / 10)))
- onlymissing = true;
-
- // Just used for easy checking whether a mine or something else was built.
- bool mine = false;
-
- std::vector<int32_t> spots_avail;
- spots_avail.resize(4);
-
- for (int32_t i = 0; i < 4; ++i)
- spots_avail.at(i) = 0;
-
- for
- (std::list<BuildableField *>::iterator i = buildable_fields.begin();
- i != buildable_fields.end();
- ++i)
- ++spots_avail.at((*i)->coords.field->nodecaps() & BUILDCAPS_SIZEMASK);
-
- int32_t expand_factor = 0;
-
- if (type != DEFENSIVE) {
- ++expand_factor;
- // check space and set the need for expansion
- if
- (spots_avail.at(BUILDCAPS_BIG)
- <
- static_cast<uint16_t>(2 + (productionsites.size() / 50)))
- expand_factor += 2;
- if
- (spots_avail.at(BUILDCAPS_MEDIUM) + spots_avail.at(BUILDCAPS_BIG)
- <
- static_cast<uint16_t>(4 + (productionsites.size() / 50)))
- expand_factor += type;
-
- uint32_t spots = spots_avail.at(BUILDCAPS_SMALL);
- spots += spots_avail.at(BUILDCAPS_MEDIUM);
- spots += spots_avail.at(BUILDCAPS_BIG);
- if (type == AGGRESSIVE)
- spots -= militarysites.size() / 20;
- if (spots < 16)
- expand_factor *= 2;
- if ((type == AGGRESSIVE) && spots < 32)
- expand_factor *= 2;
- } else {
- // check space and set the need for expansion
- if (spots_avail.at(BUILDCAPS_BIG) < 7)
- ++expand_factor;
- if (spots_avail.at(BUILDCAPS_MEDIUM) + spots_avail.at(BUILDCAPS_BIG) < 12)
- ++expand_factor;
- if
- (spots_avail.at(BUILDCAPS_SMALL) +
- spots_avail.at(BUILDCAPS_MEDIUM) +
- spots_avail.at(BUILDCAPS_BIG)
- <
- 16)
- expand_factor *= 3;
- }
-
- // don't expand when we have unoccupied military buildings
- //if (TODO) expand_factor = 0;
-
- // Defensive AIs also attack sometimes (when they want to expand)
- if (type == DEFENSIVE && expand_factor > 1)
- if (next_attack_consideration_due <= game().get_gametime())
- consider_attack(game().get_gametime());
-
-
- Building_Index proposed_building;
- int32_t proposed_priority = 0;
- Coords proposed_coords;
-
- // Remove outdated fields from blocker list
- for
- (std::list<BlockedField>::iterator i = blocked_fields.begin();
- i != blocked_fields.end();)
- if (i->blocked_until < game().get_gametime()) {
- i = blocked_fields.erase(i);
- }
- else ++i;
-
- // first scan all buildable fields for regular buildings
- for
- (std::list<BuildableField *>::iterator i = buildable_fields.begin();
- i != buildable_fields.end();
- ++i)
- {
- BuildableField * const bf = *i;
-
- if (!bf->reachable)
- continue;
-
- // Continue if field is blocked at the moment
- for
- (std::list<BlockedField>::iterator j = blocked_fields.begin();
- j != blocked_fields.end();
- ++j)
- if (j->coords == bf->coords)
- continue;
-
- assert(player);
- int32_t const maxsize =
- player->get_buildcaps(bf->coords) & BUILDCAPS_SIZEMASK;
-
- // Check all buildable buildings
- for (uint32_t j = 0; j < buildings.size(); ++j) {
- BuildingObserver & bo = buildings.at(j);
-
- if (!bo.buildable(*player))
- continue;
-
- if (bo.type == BuildingObserver::MINE)
- continue;
-
- // If there are already a lot of constructionsites, only missing
- // productionsites that produce build material are allowed
- // (perhaps they are needed to finish the other constructionsites?)
- if (onlymissing) {
- if (!(bo.type == BuildingObserver::PRODUCTIONSITE))
- continue;
- if ((bo.total_count() > 0) || !bo.prod_build_material)
- continue;
- }
-
- if (bo.desc->get_size() > maxsize)
- continue;
-
- int32_t prio = 0;
-
- if (bo.type == BuildingObserver::PRODUCTIONSITE) {
- // Don't build another building of this type, if there is already
- // one that is unoccupied at the moment
- if (bo.unoccupied)
- continue;
- if (bo.need_trees) {
- // Priority of woodcutters depend on the number of near trees
- prio += bf->trees_nearby * 3;
- prio /= 3 * (1 + bf->producers_nearby.at(bo.outputs.at(0)));
-
- // TODO improve this - it's still useless to place lumberjack huts randomly
- /*if (prio <= 0) // no, sometimes we need wood without having a forest
- continue;*/
-
- // Check if the produced wares are needed
- Ware_Index wt(static_cast<size_t>(bo.outputs.at(0)));
- container_iterate(std::list<EconomyObserver *>, economies, l) {
- // Don't check if the economy has no warehouse.
- if ((*l.current)->economy.warehouses().empty())
- continue;
- if ((*l.current)->economy.needs_ware(wt))
- prio += 1 + wares.at(bo.outputs.at(0)).preciousness;
- }
-
- if (bo.total_count() < 2) {
- prio *= 6; // big bonus for the basics
- if (bo.total_count() == 0)
- prio *= 4; // even more for the absolute basics
- }
- } else if (bo.need_stones) {
- // Priority of quarries depend on the number of near stones
- prio += bf->stones_nearby * 3;
- prio /= 3 * (1 + bf->producers_nearby.at(bo.outputs.at(0)));
- if (bo.total_count() < 2) {
- prio *= 6; // big bonus for the basics
- if (bo.total_count() == 0)
- prio *= 4; // even more for the absolute basics
- }
- } else if (bo.production_hint >= 0) {
- // production hint (f.e. associate forester with trunks)
-
- // Calculate the need for this building
- int16_t inout = wares.at(bo.production_hint).consumers;
- if
- (tribe->safe_ware_index("trunk").value()
- ==
- bo.production_hint)
- inout += total_constructionsites / 4;
- inout -= wares.at(bo.production_hint).producers;
- if (inout < 1)
- inout = 1;
- // the ware they're refreshing
- Ware_Index wt(static_cast<size_t>(bo.production_hint));
- container_iterate(std::list<EconomyObserver *>, economies, l) {
- // Don't check if the economy has no warehouse.
- if ((*l.current)->economy.warehouses().empty())
- continue;
- if ((*l.current)->economy.needs_ware(wt)) {
- prio += wares.at(bo.production_hint).preciousness * inout * 2;
- break;
- }
- }
-
- // Do not build too many of these buildings, but still care
- // to build at least two.
- // And add bonus near buildings outputting production_hint ware.
- prio += (5 * bf->producers_nearby.at(bo.production_hint)) / 2;
- prio -= bo.total_count() * 2;
- prio /= bo.total_count() + 1;
- prio += (bf->producers_nearby.at(bo.production_hint) - 1) * 5;
- if (bo.total_count() > 2)
- prio -= bo.total_count();
- else {
- prio += wares.at(bo.production_hint).preciousness;
- prio *= 3;
- }
- if (prio < 0)
- continue;
- } else if (bo.recruitment) {
- // "recruitment centeres" like the donkey farm should be build up
- // as soon as a basic infrastructure was completed.
- // and of course the defaultAI should think of further
- // constructions of that type later in game.
- prio -= 12; // start calculation with an offset
- prio += productionsites.size() + mines.size();
- prio -= (bo.total_count()) * 40;
- prio *= 2;
-
- // take care about borders and enemies
- prio = recalc_with_border_range(*bf, prio);
- } else { // "normal" productionsites
-
- // ToDo: prefer soldier producing things
- // Ware_Index const soldier_index = tribe().worker_index("soldier");
-
- if (bo.is_basic && (bo.total_count() == 0))
- prio += 100; // for very important buildings
-
- // Check if the produced wares are needed
- container_iterate(std::list<EconomyObserver *>, economies, l) {
- // Don't check if the economy has no warehouse.
- if ((*l.current)->economy.warehouses().empty())
- continue;
- for (uint32_t m = 0; m < bo.outputs.size(); ++m) {
- Ware_Index wt(static_cast<size_t>(bo.outputs.at(m)));
-
- // if we have too much of it (avoids mass storage)
- if
- ((*l.current)->economy.stock_ware(wt) > 6 *
- (*l.current)->economy.ware_target_quantity(wt).permanent)
- prio -= 20;
-
- // if the economy needs this ware
- if ((*l.current)->economy.needs_ware(wt)) {
- prio += 1 + wares.at(bo.outputs.at(m)).preciousness;
- if (bo.total_count() == 0)
- // big bonus, this site might be elemental
- prio += 3 * wares.at(bo.outputs.at(m)).preciousness;
- }
-
- // we can enhance this building. build more
- // maybe the enhancement can produce needed ware
- if (bo.desc->enhancements().size() > 0) {
- // this code builds more metalworks
- if (bo.total_count() == 0)
- prio += 2;
- if (bo.total_count() == 1)
- prio += 8;
- }
- }
- for (uint32_t m = 0; m < bo.inputs.size(); ++m) {
- Ware_Index wt(static_cast<size_t>(bo.inputs.at(m)));
-
- // if the economies don't need it: "waste" it
- if (!(*l.current)->economy.needs_ware(wt)) {
- if (bo.total_count() == 0 && bo.prod_build_material)
- // big bonus, this site might be elemental
- prio += 3 * wares.at(bo.inputs.at(m)).preciousness;
- }
- }
- }
-
- // If the produced wares are needed
- if (prio > 0) {
- int32_t inout_prio = 0;
- for (size_t k = 0; k < bo.inputs.size(); ++k) {
- inout_prio += bf->producers_nearby.at(bo.inputs.at(k));
- inout_prio -= bf->consumers_nearby.at(bo.inputs.at(k)) / 2;
- }
- for (size_t k = 0; k < bo.outputs.size(); ++k)
- inout_prio += bf->consumers_nearby.at(bo.outputs.at(k));
- prio += 2 * inout_prio;
- prio = calculate_need_for_ps(bo, prio);
- } else
- continue;
-
- // take care about borders and enemies
- prio = recalc_with_border_range(*bf, prio);
-
- // do not construct more than one building,
- // if supply line is already broken.
- if (!check_supply(bo) && bo.total_count() > 0)
- prio -= 12;
-
- }
- } else if (bo.type == BuildingObserver::MILITARYSITE) {
- if (!bf->unowned_land_nearby)
- continue;
- prio = bf->unowned_land_nearby * (1 + type);
- prio -= bf->military_influence * (5 - type);
- // set to at least 1
- prio = prio > 0 ? prio : 1;
- prio *= expand_factor;
- prio /= 2;
-
- if (bf->enemy_nearby)
- prio *= 2;
- else
- prio -= bf->military_influence * 2;
-
- if (bf->avoid_military)
- prio /= 5;
-
- prio -= militarysites.size() - productionsites.size() / (3 - type);
-
- } else if (bo.type == BuildingObserver::WAREHOUSE) {
- // Build one warehouse for ~every 35 productionsites and mines.
- // Militarysites are slightly important as well, to have a bigger
- // chance for a warehouses (containing waiting soldiers or wares
- // needed for soldier training) near the frontier.
- prio += productionsites.size() + mines.size();
- prio += militarysites.size() / 3;
- prio -= (bo.cnt_under_construction + numof_warehouses) * 35;
- prio *= 2;
-
- // take care about borders and enemies
- prio = recalc_with_border_range(*bf, prio);
-
- } else if (bo.type == BuildingObserver::TRAININGSITE) {
- // Start building trainingsites when there are already more than 50
- // other buildings. That should be enough for a working economy.
- // On the other hand only build more trainingsites of the same
- // type if the economy is really big.
- prio += productionsites.size() + militarysites.size();
- prio += mines.size();
- prio += type * 10; // +0 / +10 / +20 for DEFF/NORM/AGGR
- prio = prio / (bo.total_count() + 1);
- prio -= (bo.total_count() + 1) * 70;
-
- // take care about borders and enemies
- prio = recalc_with_border_range(*bf, prio);
- }
-
- // avoid to have too many construction sites
- // but still enable the player to build up basic productionsites
- if
- (bo.type != BuildingObserver::PRODUCTIONSITE ||
- !bo.is_basic || bo.total_count() > 0)
- prio /=
- 1 + bo.cnt_under_construction * (bo.cnt_under_construction + 1);
-
- // add big penalty if water is needed, but is not near
- if (bo.need_water) {
- if (bf->water_nearby < 3)
- continue;
- int effect = bf->water_nearby - 8;
- prio +=
- effect > 0 ?
- static_cast<int>(sqrt(static_cast<double>(effect))) : effect;
- // if same producers are nearby, then give some penalty
- for (size_t k = 0; k < bo.outputs.size(); ++k)
- if (bf->producers_nearby.at(bo.outputs.at(k)) > 0)
- prio -= 3;
- }
-
- // think of space consuming buildings nearby like farms or vineyards
- prio /= 1 + bf->space_consumers_nearby;
-
- // Stop here, if priority is 0 or less.
- if (prio <= 0)
- continue;
-
- // Prefer road side fields
- prio += bf->preferred ? 1 : 0;
-
- // don't waste good land for small huts
- prio -= (maxsize - bo.desc->get_size()) * 3;
- if (prio > proposed_priority) {
- proposed_building = bo.id;
- proposed_priority = prio;
- proposed_coords = bf->coords;
- }
- }
- }
-
- // then try all mines - as soon as basic economy is build up.
- for
- (uint32_t i = 0; i < buildings.size() && productionsites.size() > 8; ++i)
- {
- BuildingObserver & bo = buildings.at(i);
-
- if (!bo.buildable(*player) || bo.type != BuildingObserver::MINE)
- continue;
-
- // Don't build another building of this type, if there is already
- // one that is unoccupied at the moment
- if (bo.unoccupied)
- continue;
-
-
- // Only have 2 mines of a type under construction
- if (bo.cnt_under_construction > 2)
- continue;
-
- if (onlymissing)
- // Do not build mines twice, as long as other buildings might be more needed
- if (bo.total_count() > 0)
- continue;
-
-
- /* - uninteresting if a mine ware is needed - we exploit the raw material
- // Check if the produced wares are needed
- bool needed = false;
- container_iterate(std::list<EconomyObserver *>, economies, l) {
- // Don't check if the economy has no warehouse.
- if ((*l.current)->economy.warehouses().empty())
- continue;
- for (uint32_t m = 0; m < bo.outputs.size(); ++m) {
- Ware_Index wt(static_cast<size_t>(bo.outputs.at(m)));
- if ((*l.current)->economy.needs_ware(wt)) {
- needed = true;
- break;
- }
- }
- if (needed)
- break;
- }
-
- // Only try to build mines that produce needed wares.
- if (!needed)
- continue;
- */
-
- for
- (std::list<MineableField *>::iterator j = mineable_fields.begin();
- j != mineable_fields.end();
- ++j)
- {
- int32_t prio = 0;
-
- if ((*j)->coords.field->get_resources() != bo.mines)
- continue;
- else
- prio += (*j)->coords.field->get_resources_amount() * 4 / 3;
-
- // Only build mines on locations where some material can be mined
- if (prio < 2)
- continue;
-
- // Continue if field is blocked at the moment
- bool blocked = false;
- for
- (std::list<BlockedField>::iterator k = blocked_fields.begin();
- k != blocked_fields.end();
- ++k)
- if ((*j)->coords == k->coords) {
- blocked = true;
- break;
- }
- if (blocked) continue;
-
- // Check if current economy can supply enough food for production.
- for (uint32_t k = 0; k < bo.inputs.size(); ++k) {
- prio += wares.at(bo.inputs.at(k)).producers;
- prio -= wares.at(bo.inputs.at(k)).consumers / 2;
- }
-
- // our wares are needed? gimme more
- uint32_t ioprio = 0;
- for (uint32_t m = 0; m < bo.outputs.size(); ++m) {
- ioprio += 5 * wares.at(bo.outputs.at(m)).preciousness;
- }
-
- // tribes that have enhanceable mines should build more mines
- prio *= 1 + 100 / bo.mines_percent;
-
- // No plus for mines with multiple output
- ioprio /= bo.outputs.size();
- prio += ioprio;
-
- prio -= 3 * (*j)->mines_nearby * (*j)->mines_nearby;
- //prio /= 1 + bo.cnt_built * 2;
-
- // multiply with current statistics of all other buildings of this
- // type to avoid constructing buildings where already some are running
- // on low resources.
- prio *= 5 + bo.current_stats;
- prio /= 100;
-
- if (onlymissing) // mines aren't *that* important
- prio /= 3;
- if (prio > proposed_priority) {
-
- proposed_building = bo.id;
- proposed_priority = prio;
- proposed_coords = (*j)->coords;
- mine = true;
- }
- }
- }
-
- if (not proposed_building)
- return false;
-
- // do not have too many construction sites
- if
- (proposed_priority < static_cast<int32_t>(total_constructionsites)
- and not
- onlymissing) // only return here, if we do NOT try to build a missing bld
- return false;
-
- // send the command to construct a new building
- game().send_player_build
- (player_number(), proposed_coords, proposed_building);
-
- // set the type of update that is needed
- if (mine)
- m_mineable_changed = true;
- else
- m_buildable_changed = true;
-
- return true;
+bool DefaultAI::construct_building(int32_t) // (int32_t gametime)
+ {
+ // TODO make this smarter, easier and yet more effective
+
+ // TODO implement handling of seafaring
+
+ // Do not have too many constructionsites
+ uint32_t producers = mines.size() + productionsites.size();
+ bool onlymissing = false;
+ if (total_constructionsites >= (2 + (producers / 10)))
+ onlymissing = true;
+
+ // Just used for easy checking whether a mine or something else was built.
+ bool mine = false;
+
+ std::vector<int32_t> spots_avail;
+ spots_avail.resize(4);
+
+ for (int32_t i = 0; i < 4; ++i)
+ spots_avail.at(i) = 0;
+
+ for (std::list<BuildableField*>::iterator i = buildable_fields.begin();
+ i != buildable_fields.end();
+ ++i)
+ ++spots_avail.at((*i)->coords.field->nodecaps() & BUILDCAPS_SIZEMASK);
+
+ int32_t expand_factor = 0;
+
+ if (type != DEFENSIVE) {
+ ++expand_factor;
+ // check space and set the need for expansion
+ if (spots_avail.at(BUILDCAPS_BIG) < static_cast<uint16_t>(2 + (productionsites.size() / 50)))
+ expand_factor += 2;
+ if (spots_avail.at(BUILDCAPS_MEDIUM) + spots_avail.at(BUILDCAPS_BIG) <
+ static_cast<uint16_t>(4 + (productionsites.size() / 50)))
+ expand_factor += type;
+
+ uint32_t spots = spots_avail.at(BUILDCAPS_SMALL);
+ spots += spots_avail.at(BUILDCAPS_MEDIUM);
+ spots += spots_avail.at(BUILDCAPS_BIG);
+ if (type == AGGRESSIVE)
+ spots -= militarysites.size() / 20;
+ if (spots < 16)
+ expand_factor *= 2;
+ if ((type == AGGRESSIVE) && spots < 32)
+ expand_factor *= 2;
+ } else {
+ // check space and set the need for expansion
+ if (spots_avail.at(BUILDCAPS_BIG) < 7)
+ ++expand_factor;
+ if (spots_avail.at(BUILDCAPS_MEDIUM) + spots_avail.at(BUILDCAPS_BIG) < 12)
+ ++expand_factor;
+ if (spots_avail.at(BUILDCAPS_SMALL) + spots_avail.at(BUILDCAPS_MEDIUM) +
+ spots_avail.at(BUILDCAPS_BIG) <
+ 16)
+ expand_factor *= 3;
+ }
+
+ // don't expand when we have unoccupied military buildings
+ //if (TODO) expand_factor = 0;
+
+ // Defensive AIs also attack sometimes (when they want to expand)
+ if (type == DEFENSIVE && expand_factor > 1)
+ if (next_attack_consideration_due <= game().get_gametime())
+ consider_attack(game().get_gametime());
+
+ Building_Index proposed_building;
+ int32_t proposed_priority = 0;
+ Coords proposed_coords;
+
+ // Remove outdated fields from blocker list
+ for (std::list<BlockedField>::iterator i = blocked_fields.begin(); i != blocked_fields.end();)
+ if (i->blocked_until < game().get_gametime()) {
+ i = blocked_fields.erase(i);
+ } else
+ ++i;
+
+ // first scan all buildable fields for regular buildings
+ for (std::list<BuildableField*>::iterator i = buildable_fields.begin();
+ i != buildable_fields.end();
+ ++i) {
+ BuildableField* const bf = *i;
+
+ if (!bf->reachable)
+ continue;
+
+ // Continue if field is blocked at the moment
+ for (std::list<BlockedField>::iterator j = blocked_fields.begin(); j != blocked_fields.end();
+ ++j)
+ if (j->coords == bf->coords)
+ continue;
+
+ assert(player);
+ int32_t const maxsize = player->get_buildcaps(bf->coords) & BUILDCAPS_SIZEMASK;
+
+ // Check all buildable buildings
+ for (uint32_t j = 0; j < buildings.size(); ++j) {
+ BuildingObserver& bo = buildings.at(j);
+
+ if (!bo.buildable(*player))
+ continue;
+
+ if (bo.type == BuildingObserver::MINE)
+ continue;
+
+ // If there are already a lot of constructionsites, only missing
+ // productionsites that produce build material are allowed
+ // (perhaps they are needed to finish the other constructionsites?)
+ if (onlymissing) {
+ if (!(bo.type == BuildingObserver::PRODUCTIONSITE))
+ continue;
+ if ((bo.total_count() > 0) || !bo.prod_build_material)
+ continue;
+ }
+
+ if (bo.desc->get_size() > maxsize)
+ continue;
+
+ int32_t prio = 0;
+
+ if (bo.type == BuildingObserver::PRODUCTIONSITE) {
+ // Don't build another building of this type, if there is already
+ // one that is unoccupied at the moment
+ if (bo.unoccupied)
+ continue;
+ if (bo.need_trees) {
+ // Priority of woodcutters depend on the number of near trees
+ prio += bf->trees_nearby * 3;
+ prio /= 3 * (1 + bf->producers_nearby.at(bo.outputs.at(0)));
+
+ // TODO improve this - it's still useless to place lumberjack huts randomly
+ /*if (prio <= 0) // no, sometimes we need wood without having a forest
+ continue;*/
+
+ // Check if the produced wares are needed
+ Ware_Index wt(static_cast<size_t>(bo.outputs.at(0)));
+ container_iterate(std::list<EconomyObserver*>, economies, l) {
+ // Don't check if the economy has no warehouse.
+ if ((*l.current)->economy.warehouses().empty())
+ continue;
+ if ((*l.current)->economy.needs_ware(wt))
+ prio += 1 + wares.at(bo.outputs.at(0)).preciousness;
+ }
+
+ if (bo.total_count() < 2) {
+ prio *= 6; // big bonus for the basics
+ if (bo.total_count() == 0)
+ prio *= 4; // even more for the absolute basics
+ }
+ } else if (bo.need_stones) {
+ // Priority of quarries depend on the number of near stones
+ prio += bf->stones_nearby * 3;
+ prio /= 3 * (1 + bf->producers_nearby.at(bo.outputs.at(0)));
+ if (bo.total_count() < 2) {
+ prio *= 6; // big bonus for the basics
+ if (bo.total_count() == 0)
+ prio *= 4; // even more for the absolute basics
+ }
+ } else if (bo.production_hint >= 0) {
+ // production hint (f.e. associate forester with trunks)
+
+ // Calculate the need for this building
+ int16_t inout = wares.at(bo.production_hint).consumers;
+ if (tribe->safe_ware_index("trunk").value() == bo.production_hint)
+ inout += total_constructionsites / 4;
+ inout -= wares.at(bo.production_hint).producers;
+ if (inout < 1)
+ inout = 1;
+ // the ware they're refreshing
+ Ware_Index wt(static_cast<size_t>(bo.production_hint));
+ container_iterate(std::list<EconomyObserver*>, economies, l) {
+ // Don't check if the economy has no warehouse.
+ if ((*l.current)->economy.warehouses().empty())
+ continue;
+ if ((*l.current)->economy.needs_ware(wt)) {
+ prio += wares.at(bo.production_hint).preciousness * inout * 2;
+ break;
+ }
+ }
+
+ // Do not build too many of these buildings, but still care
+ // to build at least two.
+ // And add bonus near buildings outputting production_hint ware.
+ prio += (5 * bf->producers_nearby.at(bo.production_hint)) / 2;
+ prio -= bo.total_count() * 2;
+ prio /= bo.total_count() + 1;
+ prio += (bf->producers_nearby.at(bo.production_hint) - 1) * 5;
+ if (bo.total_count() > 2)
+ prio -= bo.total_count();
+ else {
+ prio += wares.at(bo.production_hint).preciousness;
+ prio *= 3;
+ }
+ if (prio < 0)
+ continue;
+ } else if (bo.recruitment) {
+ // "recruitment centeres" like the donkey farm should be build up
+ // as soon as a basic infrastructure was completed.
+ // and of course the defaultAI should think of further
+ // constructions of that type later in game.
+ prio -= 12; // start calculation with an offset
+ prio += productionsites.size() + mines.size();
+ prio -= (bo.total_count()) * 40;
+ prio *= 2;
+
+ // take care about borders and enemies
+ prio = recalc_with_border_range(*bf, prio);
+ } else { // "normal" productionsites
+
+ // ToDo: prefer soldier producing things
+ // Ware_Index const soldier_index = tribe().worker_index("soldier");
+
+ if (bo.is_basic && (bo.total_count() == 0))
+ prio += 100; // for very important buildings
+
+ // Check if the produced wares are needed
+ container_iterate(std::list<EconomyObserver*>, economies, l) {
+ // Don't check if the economy has no warehouse.
+ if ((*l.current)->economy.warehouses().empty())
+ continue;
+ for (uint32_t m = 0; m < bo.outputs.size(); ++m) {
+ Ware_Index wt(static_cast<size_t>(bo.outputs.at(m)));
+
+ // if we have too much of it (avoids mass storage)
+ if ((*l.current)->economy.stock_ware(wt) >
+ 6 * (*l.current)->economy.ware_target_quantity(wt).permanent)
+ prio -= 20;
+
+ // if the economy needs this ware
+ if ((*l.current)->economy.needs_ware(wt)) {
+ prio += 1 + wares.at(bo.outputs.at(m)).preciousness;
+ if (bo.total_count() == 0)
+ // big bonus, this site might be elemental
+ prio += 3 * wares.at(bo.outputs.at(m)).preciousness;
+ }
+
+ // we can enhance this building. build more
+ // maybe the enhancement can produce needed ware
+ if (bo.desc->enhancements().size() > 0) {
+ // this code builds more metalworks
+ if (bo.total_count() == 0)
+ prio += 2;
+ if (bo.total_count() == 1)
+ prio += 8;
+ }
+ }
+ for (uint32_t m = 0; m < bo.inputs.size(); ++m) {
+ Ware_Index wt(static_cast<size_t>(bo.inputs.at(m)));
+
+ // if the economies don't need it: "waste" it
+ if (!(*l.current)->economy.needs_ware(wt)) {
+ if (bo.total_count() == 0 && bo.prod_build_material)
+ // big bonus, this site might be elemental
+ prio += 3 * wares.at(bo.inputs.at(m)).preciousness;
+ }
+ }
+ }
+
+ // If the produced wares are needed
+ if (prio > 0) {
+ int32_t inout_prio = 0;
+ for (size_t k = 0; k < bo.inputs.size(); ++k) {
+ inout_prio += bf->producers_nearby.at(bo.inputs.at(k));
+ inout_prio -= bf->consumers_nearby.at(bo.inputs.at(k)) / 2;
+ }
+ for (size_t k = 0; k < bo.outputs.size(); ++k)
+ inout_prio += bf->consumers_nearby.at(bo.outputs.at(k));
+ prio += 2 * inout_prio;
+ prio = calculate_need_for_ps(bo, prio);
+ } else
+ continue;
+
+ // take care about borders and enemies
+ prio = recalc_with_border_range(*bf, prio);
+
+ // do not construct more than one building,
+ // if supply line is already broken.
+ if (!check_supply(bo) && bo.total_count() > 0)
+ prio -= 12;
+
+ }
+ } else if (bo.type == BuildingObserver::MILITARYSITE) {
+ if (!bf->unowned_land_nearby)
+ continue;
+ prio = bf->unowned_land_nearby * (1 + type);
+ prio -= bf->military_influence * (5 - type);
+ // set to at least 1
+ prio = prio > 0 ? prio : 1;
+ prio *= expand_factor;
+ prio /= 2;
+
+ if (bf->enemy_nearby)
+ prio *= 2;
+ else
+ prio -= bf->military_influence * 2;
+
+ if (bf->avoid_military)
+ prio /= 5;
+
+ prio -= militarysites.size() - productionsites.size() / (3 - type);
+
+ } else if (bo.type == BuildingObserver::WAREHOUSE) {
+ // Build one warehouse for ~every 35 productionsites and mines.
+ // Militarysites are slightly important as well, to have a bigger
+ // chance for a warehouses (containing waiting soldiers or wares
+ // needed for soldier training) near the frontier.
+ prio += productionsites.size() + mines.size();
+ prio += militarysites.size() / 3;
+ prio -= (bo.cnt_under_construction + numof_warehouses) * 35;
+ prio *= 2;
+
+ // take care about borders and enemies
+ prio = recalc_with_border_range(*bf, prio);
+
+ } else if (bo.type == BuildingObserver::TRAININGSITE) {
+ // Start building trainingsites when there are already more than 50
+ // other buildings. That should be enough for a working economy.
+ // On the other hand only build more trainingsites of the same
+ // type if the economy is really big.
+ prio += productionsites.size() + militarysites.size();
+ prio += mines.size();
+ prio += type * 10; // +0 / +10 / +20 for DEFF/NORM/AGGR
+ prio = prio / (bo.total_count() + 1);
+ prio -= (bo.total_count() + 1) * 70;
+
+ // take care about borders and enemies
+ prio = recalc_with_border_range(*bf, prio);
+ }
+
+ // avoid to have too many construction sites
+ // but still enable the player to build up basic productionsites
+ if (bo.type != BuildingObserver::PRODUCTIONSITE || !bo.is_basic || bo.total_count() > 0)
+ prio /= 1 + bo.cnt_under_construction * (bo.cnt_under_construction + 1);
+
+ // add big penalty if water is needed, but is not near
+ if (bo.need_water) {
+ if (bf->water_nearby < 3)
+ continue;
+ int effect = bf->water_nearby - 8;
+ prio += effect > 0 ? static_cast<int>(sqrt(static_cast<double>(effect))) : effect;
+ // if same producers are nearby, then give some penalty
+ for (size_t k = 0; k < bo.outputs.size(); ++k)
+ if (bf->producers_nearby.at(bo.outputs.at(k)) > 0)
+ prio -= 3;
+ }
+
+ // think of space consuming buildings nearby like farms or vineyards
+ prio /= 1 + bf->space_consumers_nearby;
+
+ // Stop here, if priority is 0 or less.
+ if (prio <= 0)
+ continue;
+
+ // Prefer road side fields
+ prio += bf->preferred ? 1 : 0;
+
+ // don't waste good land for small huts
+ prio -= (maxsize - bo.desc->get_size()) * 3;
+ if (prio > proposed_priority) {
+ proposed_building = bo.id;
+ proposed_priority = prio;
+ proposed_coords = bf->coords;
+ }
+ }
+ }
+
+ // then try all mines - as soon as basic economy is build up.
+ for (uint32_t i = 0; i < buildings.size() && productionsites.size() > 8; ++i) {
+ BuildingObserver& bo = buildings.at(i);
+
+ if (!bo.buildable(*player) || bo.type != BuildingObserver::MINE)
+ continue;
+
+ // Don't build another building of this type, if there is already
+ // one that is unoccupied at the moment
+ if (bo.unoccupied)
+ continue;
+
+ // Only have 2 mines of a type under construction
+ if (bo.cnt_under_construction > 2)
+ continue;
+
+ if (onlymissing)
+ // Do not build mines twice, as long as other buildings might be more needed
+ if (bo.total_count() > 0)
+ continue;
+
+ /* - uninteresting if a mine ware is needed - we exploit the raw material
+ // Check if the produced wares are needed
+ bool needed = false;
+ container_iterate(std::list<EconomyObserver *>, economies, l) {
+ // Don't check if the economy has no warehouse.
+ if ((*l.current)->economy.warehouses().empty())
+ continue;
+ for (uint32_t m = 0; m < bo.outputs.size(); ++m) {
+ Ware_Index wt(static_cast<size_t>(bo.outputs.at(m)));
+ if ((*l.current)->economy.needs_ware(wt)) {
+ needed = true;
+ break;
+ }
+ }
+ if (needed)
+ break;
+ }
+
+ // Only try to build mines that produce needed wares.
+ if (!needed)
+ continue;
+ */
+
+ for (std::list<MineableField*>::iterator j = mineable_fields.begin();
+ j != mineable_fields.end();
+ ++j) {
+ int32_t prio = 0;
+
+ if ((*j)->coords.field->get_resources() != bo.mines)
+ continue;
+ else
+ prio += (*j)->coords.field->get_resources_amount() * 4 / 3;
+
+ // Only build mines on locations where some material can be mined
+ if (prio < 2)
+ continue;
+
+ // Continue if field is blocked at the moment
+ bool blocked = false;
+ for (std::list<BlockedField>::iterator k = blocked_fields.begin();
+ k != blocked_fields.end();
+ ++k)
+ if ((*j)->coords == k->coords) {
+ blocked = true;
+ break;
+ }
+ if (blocked)
+ continue;
+
+ // Check if current economy can supply enough food for production.
+ for (uint32_t k = 0; k < bo.inputs.size(); ++k) {
+ prio += wares.at(bo.inputs.at(k)).producers;
+ prio -= wares.at(bo.inputs.at(k)).consumers / 2;
+ }
+
+ // our wares are needed? gimme more
+ uint32_t ioprio = 0;
+ for (uint32_t m = 0; m < bo.outputs.size(); ++m) {
+ ioprio += 5 * wares.at(bo.outputs.at(m)).preciousness;
+ }
+
+ // tribes that have enhanceable mines should build more mines
+ prio *= 1 + 100 / bo.mines_percent;
+
+ // No plus for mines with multiple output
+ ioprio /= bo.outputs.size();
+ prio += ioprio;
+
+ prio -= 3 * (*j)->mines_nearby * (*j)->mines_nearby;
+ //prio /= 1 + bo.cnt_built * 2;
+
+ // multiply with current statistics of all other buildings of this
+ // type to avoid constructing buildings where already some are running
+ // on low resources.
+ prio *= 5 + bo.current_stats;
+ prio /= 100;
+
+ if (onlymissing) // mines aren't *that* important
+ prio /= 3;
+ if (prio > proposed_priority) {
+
+ proposed_building = bo.id;
+ proposed_priority = prio;
+ proposed_coords = (*j)->coords;
+ mine = true;
+ }
+ }
+ }
+
+ if (not proposed_building)
+ return false;
+
+ // do not have too many construction sites
+ if (proposed_priority < static_cast<int32_t>(total_constructionsites)
+ and not onlymissing) // only return here, if we do NOT try to build a missing bld
+ return false;
+
+ // send the command to construct a new building
+ game().send_player_build(player_number(), proposed_coords, proposed_building);
+
+ // set the type of update that is needed
+ if (mine)
+ m_mineable_changed = true;
+ else
+ m_buildable_changed = true;
+
+ return true;
}
/**
* This function searches for places where a new road is needed to connect two
* economies. It then sends the request to build the road.
*/
-bool DefaultAI::construct_roads (int32_t gametime)
-{
- if (economies.size() < 2) {
- // only one economy, no need for new roads
- return false;
- }
-
- uint32_t economies_to_connect = 0;
- EconomyObserver * eo_to_connect = economies.front(); // dummy initialisation
-
- // fetch first two economies that might be connectable
- for
- (std::list<EconomyObserver *>::iterator i = economies.begin();
- economies_to_connect < 2 && i != economies.end();
- ++i)
- // Do not try to connect economies that already failed in last time.
- if ((*i)->next_connection_try <= gametime) {
- if (economies_to_connect == 1)
- eo_to_connect = *i;
- ++economies_to_connect;
- }
-
- // No need to connect, if only one economy
- if (economies_to_connect < 2)
- return false;
-
- if (eo_to_connect->flags.empty())
- return check_economies();
-
- // Check if the flag is still there and if not care about that situation
- if (!eo_to_connect->flags.front()) {
- eo_to_connect->flags.pop_front();
- return check_economies();
- }
-
- // Try to connect - this should work fine as in nearly all cases we simply
- // connect a constructionsite
- bool done = connect_flag_to_another_economy(*eo_to_connect->flags.front());
- eo_to_connect->flags.push_back(eo_to_connect->flags.front());
- eo_to_connect->flags.pop_front();
-
- if (done) {
- eo_to_connect->failed_connection_tries = 0;
- return true;
- }
-
- // If the economy consists of just one constructionsite, and the defaultAI
- // failed more than 4 times to connect, we remove the constructionsite
- if
- (eo_to_connect->failed_connection_tries > 3
- and
- eo_to_connect->flags.size() == 1)
- {
- Building * bld = eo_to_connect->flags.front()->get_building();
- if (bld) {
- BuildingObserver & bo = get_building_observer(bld->name().c_str());
- if (bo.type == BuildingObserver::CONSTRUCTIONSITE) {
- game().send_player_bulldoze(*const_cast<Flag *>(eo_to_connect->flags.front()));
- eo_to_connect->flags.pop_front();
- // Block the field at constructionsites coords for 5 minutes
- // against new construction tries.
- BlockedField blocked
- (game().map().get_fcoords(bld->get_position()),
- game().get_gametime() + 300000);
- blocked_fields.push_back(blocked);
- }
- }
- }
-
- // Unable to connect, so we let this economy wait for 30 seconds.
- eo_to_connect->next_connection_try = gametime + 30000;
- ++eo_to_connect->failed_connection_tries;
- return false;
+bool DefaultAI::construct_roads(int32_t gametime) {
+ if (economies.size() < 2) {
+ // only one economy, no need for new roads
+ return false;
+ }
+
+ uint32_t economies_to_connect = 0;
+ EconomyObserver* eo_to_connect = economies.front(); // dummy initialisation
+
+ // fetch first two economies that might be connectable
+ for (std::list<EconomyObserver*>::iterator i = economies.begin();
+ economies_to_connect < 2 && i != economies.end();
+ ++i)
+ // Do not try to connect economies that already failed in last time.
+ if ((*i)->next_connection_try <= gametime) {
+ if (economies_to_connect == 1)
+ eo_to_connect = *i;
+ ++economies_to_connect;
+ }
+
+ // No need to connect, if only one economy
+ if (economies_to_connect < 2)
+ return false;
+
+ if (eo_to_connect->flags.empty())
+ return check_economies();
+
+ // Check if the flag is still there and if not care about that situation
+ if (!eo_to_connect->flags.front()) {
+ eo_to_connect->flags.pop_front();
+ return check_economies();
+ }
+
+ // Try to connect - this should work fine as in nearly all cases we simply
+ // connect a constructionsite
+ bool done = connect_flag_to_another_economy(*eo_to_connect->flags.front());
+ eo_to_connect->flags.push_back(eo_to_connect->flags.front());
+ eo_to_connect->flags.pop_front();
+
+ if (done) {
+ eo_to_connect->failed_connection_tries = 0;
+ return true;
+ }
+
+ // If the economy consists of just one constructionsite, and the defaultAI
+ // failed more than 4 times to connect, we remove the constructionsite
+ if (eo_to_connect->failed_connection_tries > 3 and eo_to_connect->flags.size() == 1) {
+ Building* bld = eo_to_connect->flags.front()->get_building();
+ if (bld) {
+ BuildingObserver& bo = get_building_observer(bld->name().c_str());
+ if (bo.type == BuildingObserver::CONSTRUCTIONSITE) {
+ game().send_player_bulldoze(*const_cast<Flag*>(eo_to_connect->flags.front()));
+ eo_to_connect->flags.pop_front();
+ // Block the field at constructionsites coords for 5 minutes
+ // against new construction tries.
+ BlockedField blocked(game().map().get_fcoords(bld->get_position()),
+ game().get_gametime() + 300000);
+ blocked_fields.push_back(blocked);
+ }
+ }
+ }
+
+ // Unable to connect, so we let this economy wait for 30 seconds.
+ eo_to_connect->next_connection_try = gametime + 30000;
+ ++eo_to_connect->failed_connection_tries;
+ return false;
}
/// improves current road system
-bool DefaultAI::improve_roads (int32_t gametime)
-{
- // Remove flags of dead end roads, as long as no more wares are stored on them
- container_iterate(std::list<EconomyObserver *>, economies, i)
- container_iterate(std::list<Flag const *>, (*i.current)->flags, j)
- if ((*j.current)->is_dead_end() && (*j.current)->current_items() == 0) {
- game().send_player_bulldoze(*const_cast<Flag *>((*j.current)));
- j.current = (*i.current)->flags.erase(j.current);
- return true;
- }
-
- // force a split on roads that are longer than 3 parts
- // actually we do not care for loss of building capabilities - normal maps
- // should have enough space and the computer can expand it's territory.
- if (!roads.empty()) {
- const Path & path = roads.front()->get_path();
-
- if (path.get_nsteps() > 3) {
- const Map & map = game().map();
- CoordPath cp(map, path);
-
- // try to split after two steps
- CoordPath::Step_Vector::size_type i = cp.get_nsteps() - 1, j = 1;
- for (; i >= j; --i, ++j) {
- {
- const Coords c = cp.get_coords().at(i);
- if (map[c].nodecaps() & BUILDCAPS_FLAG) {
- game().send_player_build_flag (player_number(), c);
- return true;
- }
- }
- {
- const Coords c = cp.get_coords().at(j);
- if (map[c].nodecaps() & BUILDCAPS_FLAG) {
- game().send_player_build_flag (player_number(), c);
- return true;
- }
- }
- }
- // Unable to set a flag - perhaps the road was build stupid
- game().send_player_bulldoze(*const_cast<Road *>(roads.front()));
- }
-
- roads.push_back (roads.front());
- roads.pop_front ();
- }
-
- if (!economies.empty() && inhibit_road_building <= gametime) {
- EconomyObserver * eco = economies.front();
- if (!eco->flags.empty()) {
- bool finish = false;
- const Flag & flag = *eco->flags.front();
-
- // try to connect to another economy
- if (economies.size() > 1)
- finish = connect_flag_to_another_economy(flag);
-
- // try to improve the roads at this flag
- // TODO do this only on useful places - the attempt below
- // TODO unfortunatey did not work as it should...
- // if the flag is full of wares or if it is not yet a fork.
- if (!finish) //&& (!flag.has_capacity() || flag.nr_of_roads() < 3))
- finish = improve_transportation_ways(flag);
-
- // cycle through flags one at a time
- eco->flags.push_back(eco->flags.front());
- eco->flags.pop_front();
-
- // and cycle through economies
- economies.push_back(eco);
- economies.pop_front();
-
- return finish;
- } else
- // If the economy has no flag, the observers need to be updated.
- return check_economies();
- }
-
- return false;
+bool DefaultAI::improve_roads(int32_t gametime) {
+ // Remove flags of dead end roads, as long as no more wares are stored on them
+ container_iterate(std::list<EconomyObserver*>, economies, i)
+ container_iterate(std::list<Flag const*>, (*i.current)->flags, j)
+ if ((*j.current)->is_dead_end() && (*j.current)->current_items() == 0) {
+ game().send_player_bulldoze(*const_cast<Flag*>((*j.current)));
+ j.current = (*i.current)->flags.erase(j.current);
+ return true;
+ }
+
+ // force a split on roads that are longer than 3 parts
+ // actually we do not care for loss of building capabilities - normal maps
+ // should have enough space and the computer can expand it's territory.
+ if (!roads.empty()) {
+ const Path& path = roads.front()->get_path();
+
+ if (path.get_nsteps() > 3) {
+ const Map& map = game().map();
+ CoordPath cp(map, path);
+
+ // try to split after two steps
+ CoordPath::Step_Vector::size_type i = cp.get_nsteps() - 1, j = 1;
+ for (; i >= j; --i, ++j) {
+ {
+ const Coords c = cp.get_coords().at(i);
+ if (map[c].nodecaps() & BUILDCAPS_FLAG) {
+ game().send_player_build_flag(player_number(), c);
+ return true;
+ }
+ }
+ {
+ const Coords c = cp.get_coords().at(j);
+ if (map[c].nodecaps() & BUILDCAPS_FLAG) {
+ game().send_player_build_flag(player_number(), c);
+ return true;
+ }
+ }
+ }
+ // Unable to set a flag - perhaps the road was build stupid
+ game().send_player_bulldoze(*const_cast<Road*>(roads.front()));
+ }
+
+ roads.push_back(roads.front());
+ roads.pop_front();
+ }
+
+ if (!economies.empty() && inhibit_road_building <= gametime) {
+ EconomyObserver* eco = economies.front();
+ if (!eco->flags.empty()) {
+ bool finish = false;
+ const Flag& flag = *eco->flags.front();
+
+ // try to connect to another economy
+ if (economies.size() > 1)
+ finish = connect_flag_to_another_economy(flag);
+
+ // try to improve the roads at this flag
+ // TODO do this only on useful places - the attempt below
+ // TODO unfortunatey did not work as it should...
+ // if the flag is full of wares or if it is not yet a fork.
+ if (!finish) //&& (!flag.has_capacity() || flag.nr_of_roads() < 3))
+ finish = improve_transportation_ways(flag);
+
+ // cycle through flags one at a time
+ eco->flags.push_back(eco->flags.front());
+ eco->flags.pop_front();
+
+ // and cycle through economies
+ economies.push_back(eco);
+ economies.pop_front();
+
+ return finish;
+ } else
+ // If the economy has no flag, the observers need to be updated.
+ return check_economies();
+ }
+
+ return false;
}
-
// connects a specific flag to another economy
-bool DefaultAI::connect_flag_to_another_economy (const Flag & flag)
-{
- FindNodeWithFlagOrRoad functor;
- CheckStepRoadAI check(player, MOVECAPS_WALK, true);
- std::vector<Coords> reachable;
- // first look for possible destinations
- functor.economy = flag.get_economy();
- Map & map = game().map();
- map.find_reachable_fields
- (Area<FCoords>(map.get_fcoords(flag.get_position()), 16),
- &reachable,
- check,
- functor);
-
- if (reachable.empty())
- return false;
-
- // then choose the one with the shortest path
- Path * path = new Path();
- bool found = false;
- check.set_openend(false);
- Coords closest;
- container_iterate_const(std::vector<Coords>, reachable, i) {
- Path * path2 = new Path();
- if (map.findpath(flag.get_position(), *i.current, 0, *path2, check) >= 0) {
- if (!found || path->get_nsteps() > path2->get_nsteps()) {
- delete path;
- path = path2;
- path2 = NULL;
- closest = *i.current;
- found = true;
- }
- }
- delete path2;
- }
-
- if (found) {
- // if we join a road and there is no flag yet, build one
- if (dynamic_cast<const Road *>(map[closest].get_immovable()))
- game().send_player_build_flag(player_number(), closest);
-
- // and finally build the road
- game().send_player_build_road(player_number(), *path);
- return true;
- } else {
- delete path;
- return false;
- }
+bool DefaultAI::connect_flag_to_another_economy(const Flag& flag) {
+ FindNodeWithFlagOrRoad functor;
+ CheckStepRoadAI check(player, MOVECAPS_WALK, true);
+ std::vector<Coords> reachable;
+ // first look for possible destinations
+ functor.economy = flag.get_economy();
+ Map& map = game().map();
+ map.find_reachable_fields(
+ Area<FCoords>(map.get_fcoords(flag.get_position()), 16), &reachable, check, functor);
+
+ if (reachable.empty())
+ return false;
+
+ // then choose the one with the shortest path
+ Path* path = new Path();
+ bool found = false;
+ check.set_openend(false);
+ Coords closest;
+ container_iterate_const(std::vector<Coords>, reachable, i) {
+ Path* path2 = new Path();
+ if (map.findpath(flag.get_position(), *i.current, 0, *path2, check) >= 0) {
+ if (!found || path->get_nsteps() > path2->get_nsteps()) {
+ delete path;
+ path = path2;
+ path2 = NULL;
+ closest = *i.current;
+ found = true;
+ }
+ }
+ delete path2;
+ }
+
+ if (found) {
+ // if we join a road and there is no flag yet, build one
+ if (dynamic_cast<const Road*>(map[closest].get_immovable()))
+ game().send_player_build_flag(player_number(), closest);
+
+ // and finally build the road
+ game().send_player_build_road(player_number(), *path);
+ return true;
+ } else {
+ delete path;
+ return false;
+ }
}
/// adds alternative ways to already existing ones
-bool DefaultAI::improve_transportation_ways (const Flag & flag)
-{
- // First of all try to remove old building flags to clean up the road web if possible
- container_iterate(std::list<Widelands::Coords>, flags_to_be_removed, i) {
- // Maybe the flag was already removed?
- FCoords f = game().map().get_fcoords(*(i.current));
- if (upcast(Flag, other_flag, f.field->get_immovable())) {
- // Check if building is dismantled, but don't waste precious wares
- if (!other_flag->get_building() && other_flag->current_items() == 0) {
- game().send_player_bulldoze(*other_flag);
- flags_to_be_removed.erase(i.current);
- break;
- }
- } else {
- flags_to_be_removed.erase(i.current);
- break;
- }
- }
-
- std::priority_queue<NearFlag> queue;
- std::vector<NearFlag> nearflags;
-
- queue.push (NearFlag(flag, 0, 0));
- Map & map = game().map();
-
- while (!queue.empty()) {
- std::vector<NearFlag>::iterator f = find(nearflags.begin(), nearflags.end(), queue.top().flag);
- if (f != nearflags.end()) {
- queue.pop();
- continue;
- }
-
- nearflags.push_back(queue.top());
- queue.pop();
-
- NearFlag & nf = nearflags.back();
-
- for (uint8_t i = 1; i <= 6; ++i) {
- Road * const road = nf.flag->get_road(i);
-
- if (!road)
- continue;
-
- Flag * endflag = &road->get_flag(Road::FlagStart);
- if (endflag == nf.flag)
- endflag = &road->get_flag(Road::FlagEnd);
-
- int32_t dist = map.calc_distance(flag.get_position(), endflag->get_position());
- if (dist > 12) // out of range
- continue;
-
- queue.push(NearFlag(*endflag, nf.cost + road->get_path().get_nsteps(), dist));
- }
- }
-
- std::sort (nearflags.begin(), nearflags.end(), CompareDistance());
-
- CheckStepRoadAI check(player, MOVECAPS_WALK, false);
-
- for (uint32_t i = 1; i < nearflags.size(); ++i) {
- NearFlag & nf = nearflags.at(i);
-
- if (2 * nf.distance + 2 < nf.cost) {
-
- Path & path = *new Path();
- if
- (map.findpath
- (flag.get_position(), nf.flag->get_position(), 0, path, check)
- >=
- 0
- and
- static_cast<int32_t>(2 * path.get_nsteps() + 2) < nf.cost)
- {
- game().send_player_build_road (player_number(), path);
- return true;
- }
-
- delete &path;
- }
- }
-
- return false;
+bool DefaultAI::improve_transportation_ways(const Flag& flag) {
+ // First of all try to remove old building flags to clean up the road web if possible
+ container_iterate(std::list<Widelands::Coords>, flags_to_be_removed, i) {
+ // Maybe the flag was already removed?
+ FCoords f = game().map().get_fcoords(*(i.current));
+ if (upcast(Flag, other_flag, f.field->get_immovable())) {
+ // Check if building is dismantled, but don't waste precious wares
+ if (!other_flag->get_building() && other_flag->current_items() == 0) {
+ game().send_player_bulldoze(*other_flag);
+ flags_to_be_removed.erase(i.current);
+ break;
+ }
+ } else {
+ flags_to_be_removed.erase(i.current);
+ break;
+ }
+ }
+
+ std::priority_queue<NearFlag> queue;
+ std::vector<NearFlag> nearflags;
+
+ queue.push(NearFlag(flag, 0, 0));
+ Map& map = game().map();
+
+ while (!queue.empty()) {
+ std::vector<NearFlag>::iterator f =
+ find(nearflags.begin(), nearflags.end(), queue.top().flag);
+ if (f != nearflags.end()) {
+ queue.pop();
+ continue;
+ }
+
+ nearflags.push_back(queue.top());
+ queue.pop();
+
+ NearFlag& nf = nearflags.back();
+
+ for (uint8_t i = 1; i <= 6; ++i) {
+ Road* const road = nf.flag->get_road(i);
+
+ if (!road)
+ continue;
+
+ Flag* endflag = &road->get_flag(Road::FlagStart);
+ if (endflag == nf.flag)
+ endflag = &road->get_flag(Road::FlagEnd);
+
+ int32_t dist = map.calc_distance(flag.get_position(), endflag->get_position());
+ if (dist > 12) // out of range
+ continue;
+
+ queue.push(NearFlag(*endflag, nf.cost + road->get_path().get_nsteps(), dist));
+ }
+ }
+
+ std::sort(nearflags.begin(), nearflags.end(), CompareDistance());
+
+ CheckStepRoadAI check(player, MOVECAPS_WALK, false);
+
+ for (uint32_t i = 1; i < nearflags.size(); ++i) {
+ NearFlag& nf = nearflags.at(i);
+
+ if (2 * nf.distance + 2 < nf.cost) {
+
+ Path& path = *new Path();
+ if (map.findpath(flag.get_position(), nf.flag->get_position(), 0, path, check) >=
+ 0 and static_cast<int32_t>(2 * path.get_nsteps() + 2) < nf.cost) {
+ game().send_player_build_road(player_number(), path);
+ return true;
+ }
+
+ delete &path;
+ }
+ }
+
+ return false;
}
-
/**
* Checks if anything in one of the economies changed and takes care for these
* changes.
*
* \returns true, if something was changed.
*/
-bool DefaultAI::check_economies ()
-{
- while (!new_flags.empty()) {
- const Flag & flag = *new_flags.front();
- new_flags.pop_front();
- get_economy_observer(flag.economy())->flags.push_back (&flag);
- }
-
- container_iterate(std::list<EconomyObserver *>, economies, i) {
- // check if any flag has changed its economy
- std::list<Flag const *> &fl = (*i.current)->flags;
- for (std::list<Flag const *>::iterator j = fl.begin(); j != fl.end();) {
- if (&(*i.current)->economy != &(*j)->economy()) {
- get_economy_observer((*j)->economy())->flags.push_back(*j);
- j = fl.erase(j);
- } else
- ++j;
- }
-
- // if there are no more flags in this economy,
- // we no longer need it's observer
- if ((*i.current)->flags.empty()) {
- delete *i.current;
- economies.erase(i.current);
- return true;
- }
- }
- return false;
+bool DefaultAI::check_economies() {
+ while (!new_flags.empty()) {
+ const Flag& flag = *new_flags.front();
+ new_flags.pop_front();
+ get_economy_observer(flag.economy())->flags.push_back(&flag);
+ }
+
+ container_iterate(std::list<EconomyObserver*>, economies, i) {
+ // check if any flag has changed its economy
+ std::list<Flag const*>& fl = (*i.current)->flags;
+ for (std::list<Flag const*>::iterator j = fl.begin(); j != fl.end();) {
+ if (&(*i.current)->economy != &(*j)->economy()) {
+ get_economy_observer((*j)->economy())->flags.push_back(*j);
+ j = fl.erase(j);
+ } else
+ ++j;
+ }
+
+ // if there are no more flags in this economy,
+ // we no longer need it's observer
+ if ((*i.current)->flags.empty()) {
+ delete *i.current;
+ economies.erase(i.current);
+ return true;
+ }
+ }
+ return false;
}
/**
@@ -1602,185 +1484,171 @@
*
* \returns true, if something was changed.
*/
-bool DefaultAI::check_productionsites(int32_t gametime)
-{
- if ((next_productionsite_check_due > gametime) || productionsites.empty())
- return false;
- next_productionsite_check_due = gametime + 1300;
-
- // Get link to productionsite that should be checked
- ProductionSiteObserver & site = productionsites.front();
- bool changed = false;
-
- // Get max radius of recursive workarea
- Workarea_Info::size_type radius = 0;
-
- const Workarea_Info & workarea_info = site.bo->desc->m_workarea_info;
- container_iterate_const(Workarea_Info, workarea_info, i)
- if (radius < i.current->first)
- radius = i.current->first;
-
- Map & map = game().map();
-
- // Lumberjack / Woodcutter handling
- if
- (site.bo->need_trees
- and
- map.find_immovables
- (Area<FCoords>(map.get_fcoords(site.site->get_position()), radius),
- 0,
- FindImmovableAttribute(Map_Object_Descr::get_attribute_id("tree")))
- ==
- 0)
- {
- if (site.site->get_statistics_percent() == 0) {
- // Do not destruct the last lumberjack - perhaps some small trees are
- // near, a forester will plant some trees or some new trees will seed
- // in reach. Computer players can easily run out of wood if this check
- // is not done.
- if (site.bo->cnt_built == 1)
- return false;
- // destruct the building and it's flag (via flag destruction)
- // the destruction of the flag avoids that defaultAI will have too many
- // unused roads - if needed the road will be rebuild directly.
- flags_to_be_removed.push_back(site.site->base_flag().get_position());
- game().send_player_dismantle(*site.site);
- return true;
- }
- }
-
- // Quarry handling
- if
- (site.bo->need_stones
- and
- map.find_immovables
- (Area<FCoords>(map.get_fcoords(site.site->get_position()), radius),
- 0,
- FindImmovableAttribute(Map_Object_Descr::get_attribute_id("stone")))
- ==
- 0)
- {
- // destruct the building and it's flag (via flag destruction)
- // the destruction of the flag avoids that defaultAI will have too many
- // unused roads - if needed the road will be rebuild directly.
- flags_to_be_removed.push_back(site.site->base_flag().get_position());
- game().send_player_dismantle(*site.site);
- return true;
- }
-
- // All other productionsites without input...
- if
- (site.bo->inputs.empty() // does not consume anything
- and
- site.bo->production_hint == -1 // not a renewing building (forester...)
- and
- site.builttime + 600000 < game().get_gametime() // > 10 minutes old
- and
- site.site->can_start_working()) // building is occupied
- {
- if (site.site->get_statistics_percent() == 0) { // production stats == 0%
- ++site.statszero;
- // Only continue here, if at least 3 following times, the stats were 0%
- if (site.statszero >= 3) {
- // Do not destruct building, if it's basic and the last of this
- // type left.
- if (site.bo->is_basic && site.bo->cnt_built <= 1)
- return false;
-
- // If building seems to be useless, think about destructing it and
- // it's flag (via flag destruction) more or less randomly. The
- // destruction of the flag avoids that defaultAI will have too many
- // unused roads - if needed the road will be rebuild directly.
- //
- // Add a bonus if one building of this type is still unoccupied
- if (((game().get_gametime() % 4) + site.bo->unoccupied) > 2) {
- flags_to_be_removed.push_back(site.site->base_flag().get_position());
- game().send_player_dismantle(*site.site);
- return true;
- }
- else
- return false;
- }
- return false;
- } else
- site.statszero = 0; // reset zero counter
- }
-
- // Do not have too many constructionsites
- uint32_t producers = mines.size() + productionsites.size();
- if (total_constructionsites >= (5 + (producers / 10)))
- return false;
-
- // Check whether building is enhanceable and if wares of the enhanced
- // buildings are needed. If yes consider an upgrade.
- std::set<Building_Index> enhancements = site.site->enhancements();
- int32_t maxprio = 0;
- Building_Index enbld;
- container_iterate_const(std::set<Building_Index>, enhancements, x) {
- // Only enhance buildings that are allowed (scenario mode)
- if (player->is_building_type_allowed(*x.current)) {
- const Building_Descr & bld = *tribe->get_building_descr(*x.current);
- BuildingObserver & en_bo = get_building_observer(bld.name().c_str());
-
- // Don't enhance this building, if there is already one of same type
- // under construction
- if (en_bo.cnt_under_construction > 0)
- continue;
-
- // don't upgrade without workers
- if (!site.site->has_workers(*x.current, game()))
- continue;
-
- int32_t prio = 0; // priority for enhancement
-
- // Find new outputs of enhanced building
- std::vector<int16_t> & current_outputs = site.bo->outputs;
- std::vector<int16_t> new_outputs;
- for (uint16_t i = 0; i < en_bo.outputs.size(); ++i) {
- for (uint16_t j = 0; j < current_outputs.size(); ++j)
- if (current_outputs.at(j) == en_bo.outputs.at(i)) {
- Ware_Index wt(static_cast<size_t>(current_outputs.at(j)));
- if (site.site->economy().needs_ware(wt))
- prio -=
- (2 + wares.at(current_outputs.at(j)).preciousness) / 2;
- continue;
- }
- new_outputs.push_back(static_cast<int16_t>(i));
- }
-
- // Check if the new wares are needed in economy of the building
- for (uint32_t i = 0; i < new_outputs.size(); ++i) {
- Ware_Index wt(static_cast<size_t>(new_outputs.at(i)));
- if (site.site->economy().needs_ware(wt))
- prio += 2 + wares.at(new_outputs.at(i)).preciousness;
- }
-
- // Compare the number of buildings of current type with the number
- // of buildings of enhanced type
- prio += (site.bo->total_count() - en_bo.total_count()) * 2;
-
- // If the new wares are needed
- if (prio > 0) {
- prio = calculate_need_for_ps(en_bo, prio);
- if (prio > maxprio) {
- maxprio = prio;
- enbld = (*x.current);
- }
- }
- }
- }
-
- // Enhance if enhanced building is useful
- // additional: we dont want to lose the old building
- if (maxprio > 0 && site.bo->total_count() > 1) {
- game().send_player_enhance_building(*site.site, enbld);
- changed = true;
- }
-
- // Reorder and set new values;
- productionsites.push_back(productionsites.front());
- productionsites.pop_front();
- return changed;
+bool DefaultAI::check_productionsites(int32_t gametime) {
+ if ((next_productionsite_check_due > gametime) || productionsites.empty())
+ return false;
+ next_productionsite_check_due = gametime + 1300;
+
+ // Get link to productionsite that should be checked
+ ProductionSiteObserver& site = productionsites.front();
+ bool changed = false;
+
+ // Get max radius of recursive workarea
+ Workarea_Info::size_type radius = 0;
+
+ const Workarea_Info& workarea_info = site.bo->desc->m_workarea_info;
+ container_iterate_const(Workarea_Info, workarea_info, i)
+ if (radius < i.current->first)
+ radius = i.current->first;
+
+ Map& map = game().map();
+
+ // Lumberjack / Woodcutter handling
+ if (site.bo->need_trees and map.find_immovables(
+ Area<FCoords>(map.get_fcoords(site.site->get_position()), radius),
+ 0,
+ FindImmovableAttribute(Map_Object_Descr::get_attribute_id("tree"))) ==
+ 0) {
+ if (site.site->get_statistics_percent() == 0) {
+ // Do not destruct the last lumberjack - perhaps some small trees are
+ // near, a forester will plant some trees or some new trees will seed
+ // in reach. Computer players can easily run out of wood if this check
+ // is not done.
+ if (site.bo->cnt_built == 1)
+ return false;
+ // destruct the building and it's flag (via flag destruction)
+ // the destruction of the flag avoids that defaultAI will have too many
+ // unused roads - if needed the road will be rebuild directly.
+ flags_to_be_removed.push_back(site.site->base_flag().get_position());
+ game().send_player_dismantle(*site.site);
+ return true;
+ }
+ }
+
+ // Quarry handling
+ if (site.bo->need_stones and map.find_immovables(
+ Area<FCoords>(map.get_fcoords(site.site->get_position()), radius),
+ 0,
+ FindImmovableAttribute(Map_Object_Descr::get_attribute_id("stone"))) ==
+ 0) {
+ // destruct the building and it's flag (via flag destruction)
+ // the destruction of the flag avoids that defaultAI will have too many
+ // unused roads - if needed the road will be rebuild directly.
+ flags_to_be_removed.push_back(site.site->base_flag().get_position());
+ game().send_player_dismantle(*site.site);
+ return true;
+ }
+
+ // All other productionsites without input...
+ if (site.bo->inputs.empty() // does not consume anything
+ and site.bo->production_hint ==
+ -1 // not a renewing building (forester...)
+ and site.builttime +
+ 600000 <
+ game().get_gametime() // > 10 minutes old
+ and site.site->can_start_working()) // building is occupied
+ {
+ if (site.site->get_statistics_percent() == 0) { // production stats == 0%
+ ++site.statszero;
+ // Only continue here, if at least 3 following times, the stats were 0%
+ if (site.statszero >= 3) {
+ // Do not destruct building, if it's basic and the last of this
+ // type left.
+ if (site.bo->is_basic && site.bo->cnt_built <= 1)
+ return false;
+
+ // If building seems to be useless, think about destructing it and
+ // it's flag (via flag destruction) more or less randomly. The
+ // destruction of the flag avoids that defaultAI will have too many
+ // unused roads - if needed the road will be rebuild directly.
+ //
+ // Add a bonus if one building of this type is still unoccupied
+ if (((game().get_gametime() % 4) + site.bo->unoccupied) > 2) {
+ flags_to_be_removed.push_back(site.site->base_flag().get_position());
+ game().send_player_dismantle(*site.site);
+ return true;
+ } else
+ return false;
+ }
+ return false;
+ } else
+ site.statszero = 0; // reset zero counter
+ }
+
+ // Do not have too many constructionsites
+ uint32_t producers = mines.size() + productionsites.size();
+ if (total_constructionsites >= (5 + (producers / 10)))
+ return false;
+
+ // Check whether building is enhanceable and if wares of the enhanced
+ // buildings are needed. If yes consider an upgrade.
+ std::set<Building_Index> enhancements = site.site->enhancements();
+ int32_t maxprio = 0;
+ Building_Index enbld;
+ container_iterate_const(std::set<Building_Index>, enhancements, x) {
+ // Only enhance buildings that are allowed (scenario mode)
+ if (player->is_building_type_allowed(*x.current)) {
+ const Building_Descr& bld = *tribe->get_building_descr(*x.current);
+ BuildingObserver& en_bo = get_building_observer(bld.name().c_str());
+
+ // Don't enhance this building, if there is already one of same type
+ // under construction
+ if (en_bo.cnt_under_construction > 0)
+ continue;
+
+ // don't upgrade without workers
+ if (!site.site->has_workers(*x.current, game()))
+ continue;
+
+ int32_t prio = 0; // priority for enhancement
+
+ // Find new outputs of enhanced building
+ std::vector<int16_t>& current_outputs = site.bo->outputs;
+ std::vector<int16_t> new_outputs;
+ for (uint16_t i = 0; i < en_bo.outputs.size(); ++i) {
+ for (uint16_t j = 0; j < current_outputs.size(); ++j)
+ if (current_outputs.at(j) == en_bo.outputs.at(i)) {
+ Ware_Index wt(static_cast<size_t>(current_outputs.at(j)));
+ if (site.site->economy().needs_ware(wt))
+ prio -= (2 + wares.at(current_outputs.at(j)).preciousness) / 2;
+ continue;
+ }
+ new_outputs.push_back(static_cast<int16_t>(i));
+ }
+
+ // Check if the new wares are needed in economy of the building
+ for (uint32_t i = 0; i < new_outputs.size(); ++i) {
+ Ware_Index wt(static_cast<size_t>(new_outputs.at(i)));
+ if (site.site->economy().needs_ware(wt))
+ prio += 2 + wares.at(new_outputs.at(i)).preciousness;
+ }
+
+ // Compare the number of buildings of current type with the number
+ // of buildings of enhanced type
+ prio += (site.bo->total_count() - en_bo.total_count()) * 2;
+
+ // If the new wares are needed
+ if (prio > 0) {
+ prio = calculate_need_for_ps(en_bo, prio);
+ if (prio > maxprio) {
+ maxprio = prio;
+ enbld = (*x.current);
+ }
+ }
+ }
+ }
+
+ // Enhance if enhanced building is useful
+ // additional: we dont want to lose the old building
+ if (maxprio > 0 && site.bo->total_count() > 1) {
+ game().send_player_enhance_building(*site.site, enbld);
+ changed = true;
+ }
+
+ // Reorder and set new values;
+ productionsites.push_back(productionsites.front());
+ productionsites.pop_front();
+ return changed;
}
/**
@@ -1789,69 +1657,66 @@
*
* \returns true, if something was changed.
*/
-bool DefaultAI::check_mines(int32_t const gametime)
-{
- if ((next_mine_check_due > gametime) || mines.empty())
- return false;
- next_mine_check_due = gametime + 1000;
-
- // Get link to productionsite that should be checked
- ProductionSiteObserver & site = mines.front();
- Map & map = game().map();
- Field * field = map.get_fcoords(site.site->get_position()).field;
-
- // Don't try to enhance as long as stats are not down to 0% - it is possible,
- // that some neighbour fields still have resources
- if (site.site->get_statistics_percent() > 0)
- return false;
-
- // Check if mine ran out of resources
- uint8_t current = field->get_resources_amount();
- if (current < 1) {
- // destruct the building and it's flag (via flag destruction)
- // the destruction of the flag avoids that defaultAI will have too many
- // unused roads - if needed the road will be rebuild directly.
- flags_to_be_removed.push_back(site.site->base_flag().get_position());
- game().send_player_dismantle(*site.site);
- return true;
- }
-
- // Check whether building is enhanceable. If yes consider an upgrade.
- std::set<Building_Index> enhancements = site.site->enhancements();
- int32_t maxprio = 0;
- Building_Index enbld;
- bool changed = false;
- container_iterate_const(std::set<Building_Index>, enhancements, x) {
- // Only enhance buildings that are allowed (scenario mode)
- if (player->is_building_type_allowed(*x.current)) {
-
- // Check if mine needs an enhancement to mine more resources
- uint8_t const until =
- field->get_starting_res_amount() * (100 - site.bo->mines_percent)
- /
- 100;
- if (until >= current) {
- // add some randomness - just for the case if more than one
- // enhancement is available (not in any tribe yet)
- int32_t const prio = time(0) % 3 + 1;
- if (prio > maxprio) {
- maxprio = prio;
- enbld = (*x.current);
- }
- }
- }
- }
-
- // Enhance if enhanced building is useful
- if (maxprio > 0) {
- game().send_player_enhance_building(*site.site, enbld);
- changed = true;
- }
-
- // Reorder and set new values;
- mines.push_back(mines.front());
- mines.pop_front();
- return changed;
+bool DefaultAI::check_mines(int32_t const gametime) {
+ if ((next_mine_check_due > gametime) || mines.empty())
+ return false;
+ next_mine_check_due = gametime + 1000;
+
+ // Get link to productionsite that should be checked
+ ProductionSiteObserver& site = mines.front();
+ Map& map = game().map();
+ Field* field = map.get_fcoords(site.site->get_position()).field;
+
+ // Don't try to enhance as long as stats are not down to 0% - it is possible,
+ // that some neighbour fields still have resources
+ if (site.site->get_statistics_percent() > 0)
+ return false;
+
+ // Check if mine ran out of resources
+ uint8_t current = field->get_resources_amount();
+ if (current < 1) {
+ // destruct the building and it's flag (via flag destruction)
+ // the destruction of the flag avoids that defaultAI will have too many
+ // unused roads - if needed the road will be rebuild directly.
+ flags_to_be_removed.push_back(site.site->base_flag().get_position());
+ game().send_player_dismantle(*site.site);
+ return true;
+ }
+
+ // Check whether building is enhanceable. If yes consider an upgrade.
+ std::set<Building_Index> enhancements = site.site->enhancements();
+ int32_t maxprio = 0;
+ Building_Index enbld;
+ bool changed = false;
+ container_iterate_const(std::set<Building_Index>, enhancements, x) {
+ // Only enhance buildings that are allowed (scenario mode)
+ if (player->is_building_type_allowed(*x.current)) {
+
+ // Check if mine needs an enhancement to mine more resources
+ uint8_t const until =
+ field->get_starting_res_amount() * (100 - site.bo->mines_percent) / 100;
+ if (until >= current) {
+ // add some randomness - just for the case if more than one
+ // enhancement is available (not in any tribe yet)
+ int32_t const prio = time(0) % 3 + 1;
+ if (prio > maxprio) {
+ maxprio = prio;
+ enbld = (*x.current);
+ }
+ }
+ }
+ }
+
+ // Enhance if enhanced building is useful
+ if (maxprio > 0) {
+ game().send_player_enhance_building(*site.site, enbld);
+ changed = true;
+ }
+
+ // Reorder and set new values;
+ mines.push_back(mines.front());
+ mines.pop_front();
+ return changed;
}
/**
@@ -1862,120 +1727,114 @@
*
* \returns true if something was changed
*/
-bool DefaultAI::check_militarysites(int32_t gametime)
-{
- if (next_militarysite_check_due > gametime)
- return false;
-
- // Only useable, if defaultAI owns at least one militarysite
- if (militarysites.empty())
- return false;
-
- // Check next militarysite
- bool changed = false;
- Map & map = game().map();
- MilitarySite * ms = militarysites.front().site;
- uint32_t const vision = ms->vision_range();
- FCoords f = map.get_fcoords(ms->get_position());
-
- // look if there is any enemy land nearby
- FindNodeUnowned find_unowned(player, game(), true);
-
- if (map.find_fields(Area<FCoords>(f, vision), 0, find_unowned) == 0) {
- // If no enemy in sight - decrease the number of stationed soldiers
- // as long as it is > 1 - BUT take care that there is a warehouse in the
- // same economy where the thrown out soldiers can go to.
- if (ms->economy().warehouses().size()) {
- uint32_t const j = ms->soldierCapacity();
- if (j > 1)
- game().send_player_change_soldier_capacity(*ms, -1);
-
- // if the building is in inner land and other militarysites still
- // hold the miliary influence of the field, consider to destruct the
- // building to free some building space.
- else {
- // treat this field like a buildable and write military info to it.
- BuildableField bf(f);
- update_buildable_field(bf, vision, true);
-
- // watch out if there is any unowned land in vision range. If there
- // is none, there must be another building nearer to the frontier.
- if (bf.unowned_land_nearby == 0) {
- // bigger buildings are only checked after all smaller
- // ones are at least one time checked.
- if (militarysites.front().checks == 0) {
- // If the military influence of other near buildings is higher
- // than the own doubled max SoldierCapacity destruct the
- // building and it's flag (via flag destruction)
- // the destruction of the flag avoids that defaultAI will have
- // too many unused roads - if needed the road will be rebuild
- // directly.
- if (static_cast<int32_t>(ms->maxSoldierCapacity() * 4) < bf.military_influence) {
- if (ms->get_playercaps() & Widelands::Building::PCap_Dismantle) {
- flags_to_be_removed.push_back(ms->base_flag().get_position());
- game().send_player_dismantle(*ms);
- } else {
- game().send_player_bulldoze(*ms);
- }
- }
-
- // Else consider enhancing the building (if possible)
- else {
- // Do not have too many constructionsites
- uint32_t producers = mines.size() + productionsites.size();
- if (total_constructionsites >= (5 + (producers / 10)))
- goto reorder;
- std::set<Building_Index> enhancements = ms->enhancements();
- int32_t maxprio = 10000; // surely never reached
- Building_Index enbld;
- container_iterate_const
- (std::set<Building_Index>, enhancements, x)
- {
- // Only enhance building to allowed (scenario mode)
- if (player->is_building_type_allowed(*x.current)) {
- const Building_Descr & bld =
- *tribe->get_building_descr(*x.current);
- BuildingObserver & en_bo =
- get_building_observer(bld.name().c_str());
-
- // Don't enhance this building, if there is
- // already one of same type under construction
- if (en_bo.cnt_under_construction > 0)
- continue;
- if (en_bo.cnt_built < maxprio) {
- maxprio = en_bo.cnt_built;
- enbld = (*x.current);
- }
- }
- }
- // Enhance if enhanced building is useful
- if (maxprio < 10000) {
- game().send_player_enhance_building(*ms, enbld);
- changed = true;
- }
- }
- } else
- --militarysites.front().checks;
- }
- }
- }
- } else {
- // If an enemy is in sight and the number of stationed soldier is not
- // at maximum - set it to maximum.
- uint32_t const j = ms->maxSoldierCapacity();
- uint32_t const k = ms->soldierCapacity();
- if (j > k)
- game().send_player_change_soldier_capacity(*ms, j - k);
- changed = true;
- }
- reorder:;
- militarysites.push_back(militarysites.front());
- militarysites.pop_front();
- next_militarysite_check_due = gametime + 1000;
- return changed;
+bool DefaultAI::check_militarysites(int32_t gametime) {
+ if (next_militarysite_check_due > gametime)
+ return false;
+
+ // Only useable, if defaultAI owns at least one militarysite
+ if (militarysites.empty())
+ return false;
+
+ // Check next militarysite
+ bool changed = false;
+ Map& map = game().map();
+ MilitarySite* ms = militarysites.front().site;
+ uint32_t const vision = ms->vision_range();
+ FCoords f = map.get_fcoords(ms->get_position());
+
+ // look if there is any enemy land nearby
+ FindNodeUnowned find_unowned(player, game(), true);
+
+ if (map.find_fields(Area<FCoords>(f, vision), 0, find_unowned) == 0) {
+ // If no enemy in sight - decrease the number of stationed soldiers
+ // as long as it is > 1 - BUT take care that there is a warehouse in the
+ // same economy where the thrown out soldiers can go to.
+ if (ms->economy().warehouses().size()) {
+ uint32_t const j = ms->soldierCapacity();
+ if (j > 1)
+ game().send_player_change_soldier_capacity(*ms, -1);
+
+ // if the building is in inner land and other militarysites still
+ // hold the miliary influence of the field, consider to destruct the
+ // building to free some building space.
+ else {
+ // treat this field like a buildable and write military info to it.
+ BuildableField bf(f);
+ update_buildable_field(bf, vision, true);
+
+ // watch out if there is any unowned land in vision range. If there
+ // is none, there must be another building nearer to the frontier.
+ if (bf.unowned_land_nearby == 0) {
+ // bigger buildings are only checked after all smaller
+ // ones are at least one time checked.
+ if (militarysites.front().checks == 0) {
+ // If the military influence of other near buildings is higher
+ // than the own doubled max SoldierCapacity destruct the
+ // building and it's flag (via flag destruction)
+ // the destruction of the flag avoids that defaultAI will have
+ // too many unused roads - if needed the road will be rebuild
+ // directly.
+ if (static_cast<int32_t>(ms->maxSoldierCapacity() * 4) < bf.military_influence) {
+ if (ms->get_playercaps() & Widelands::Building::PCap_Dismantle) {
+ flags_to_be_removed.push_back(ms->base_flag().get_position());
+ game().send_player_dismantle(*ms);
+ } else {
+ game().send_player_bulldoze(*ms);
+ }
+ }
+
+ // Else consider enhancing the building (if possible)
+ else {
+ // Do not have too many constructionsites
+ uint32_t producers = mines.size() + productionsites.size();
+ if (total_constructionsites >= (5 + (producers / 10)))
+ goto reorder;
+ std::set<Building_Index> enhancements = ms->enhancements();
+ int32_t maxprio = 10000; // surely never reached
+ Building_Index enbld;
+ container_iterate_const(std::set<Building_Index>, enhancements, x) {
+ // Only enhance building to allowed (scenario mode)
+ if (player->is_building_type_allowed(*x.current)) {
+ const Building_Descr& bld = *tribe->get_building_descr(*x.current);
+ BuildingObserver& en_bo = get_building_observer(bld.name().c_str());
+
+ // Don't enhance this building, if there is
+ // already one of same type under construction
+ if (en_bo.cnt_under_construction > 0)
+ continue;
+ if (en_bo.cnt_built < maxprio) {
+ maxprio = en_bo.cnt_built;
+ enbld = (*x.current);
+ }
+ }
+ }
+ // Enhance if enhanced building is useful
+ if (maxprio < 10000) {
+ game().send_player_enhance_building(*ms, enbld);
+ changed = true;
+ }
+ }
+ } else
+ --militarysites.front().checks;
+ }
+ }
+ }
+ } else {
+ // If an enemy is in sight and the number of stationed soldier is not
+ // at maximum - set it to maximum.
+ uint32_t const j = ms->maxSoldierCapacity();
+ uint32_t const k = ms->soldierCapacity();
+ if (j > k)
+ game().send_player_change_soldier_capacity(*ms, j - k);
+ changed = true;
+ }
+reorder:
+ militarysites.push_back(militarysites.front());
+ militarysites.pop_front();
+ next_militarysite_check_due = gametime + 1000;
+ return changed;
}
-
/**
* This function takes care about the unowned and opposing territory and
* recalculates the priority for none military buildings depending on the
@@ -1986,295 +1845,254 @@
*
* \returns the recalculated priority
*/
-int32_t DefaultAI::recalc_with_border_range(const BuildableField & bf, int32_t prio)
-{
- // Prefer building space in the inner land.
- prio /= (1 + (bf.unowned_land_nearby / 4));
-
- // Especially places near the frontier to the enemies are unlikely
- // NOTE take care about the type of computer player. The more
- // NOTE aggressive a computer player is, the more important is
- // NOTE this check. So we add \var type as bonus.
- if (bf.enemy_nearby)
- prio /= (3 + type);
-
- return prio;
+int32_t DefaultAI::recalc_with_border_range(const BuildableField& bf, int32_t prio) {
+ // Prefer building space in the inner land.
+ prio /= (1 + (bf.unowned_land_nearby / 4));
+
+ // Especially places near the frontier to the enemies are unlikely
+ // NOTE take care about the type of computer player. The more
+ // NOTE aggressive a computer player is, the more important is
+ // NOTE this check. So we add \var type as bonus.
+ if (bf.enemy_nearby)
+ prio /= (3 + type);
+
+ return prio;
}
-
-
/**
* calculates how much a productionsite of type \arg bo is needed inside it's
* economy. \arg prio is initial value for this calculation
*
* \returns the calculated priority
*/
-int32_t DefaultAI::calculate_need_for_ps(BuildingObserver & bo, int32_t prio)
-{
- // some randomness to avoid that defaultAI is building always
- // the same (always == another game but same map with
- // defaultAI on same coords)
- prio += time(0) % 3 - 1;
-
- // check if current economy can supply enough material for
- // production.
- for (uint32_t k = 0; k < bo.inputs.size(); ++k) {
- prio += 2 * wares.at(bo.inputs.at(k)).producers;
- prio -= wares.at(bo.inputs.at(k)).consumers;
- }
- if (bo.inputs.empty())
- prio += 4;
-
- int32_t output_prio = 0;
- for (uint32_t k = 0; k < bo.outputs.size(); ++k) {
- WareObserver & wo = wares.at(bo.outputs.at(k));
- if (wo.consumers > 0) {
- output_prio += wo.preciousness;
- output_prio += wo.consumers * 2;
- output_prio -= wo.producers * 2;
- if (bo.total_count() == 0)
- output_prio += 10; // add a big bonus
- }
- }
- if (bo.outputs.size() > 1)
- output_prio = static_cast<int32_t>
- (ceil(output_prio / sqrt(static_cast<double>(bo.outputs.size()))));
- prio += 2 * output_prio;
-
- // If building consumes some wares, multiply with current statistics of all
- // other buildings of this type to avoid constructing buildings where already
- // some are running on low resources.
- // Else at least add a part of the stats t the calculation.
- if (!bo.inputs.empty()) {
- prio *= bo.current_stats;
- prio /= 100;
- } else
- prio = ((prio * bo.current_stats) / 100) + (prio / 2);
-
- return prio;
-}
-
-
-void DefaultAI::consider_productionsite_influence
- (BuildableField & field, Coords coords, const BuildingObserver & bo)
-{
- if
- (bo.space_consumer
- and
- game().map().calc_distance(coords, field.coords) < 4)
- ++field.space_consumers_nearby;
-
- for (size_t i = 0; i < bo.inputs.size(); ++i)
- ++field.consumers_nearby.at(bo.inputs.at(i));
- for (size_t i = 0; i < bo.outputs.size(); ++i)
- ++field.producers_nearby.at(bo.outputs.at(i));
-}
-
+int32_t DefaultAI::calculate_need_for_ps(BuildingObserver& bo, int32_t prio) {
+ // some randomness to avoid that defaultAI is building always
+ // the same (always == another game but same map with
+ // defaultAI on same coords)
+ prio += time(0) % 3 - 1;
+
+ // check if current economy can supply enough material for
+ // production.
+ for (uint32_t k = 0; k < bo.inputs.size(); ++k) {
+ prio += 2 * wares.at(bo.inputs.at(k)).producers;
+ prio -= wares.at(bo.inputs.at(k)).consumers;
+ }
+ if (bo.inputs.empty())
+ prio += 4;
+
+ int32_t output_prio = 0;
+ for (uint32_t k = 0; k < bo.outputs.size(); ++k) {
+ WareObserver& wo = wares.at(bo.outputs.at(k));
+ if (wo.consumers > 0) {
+ output_prio += wo.preciousness;
+ output_prio += wo.consumers * 2;
+ output_prio -= wo.producers * 2;
+ if (bo.total_count() == 0)
+ output_prio += 10; // add a big bonus
+ }
+ }
+ if (bo.outputs.size() > 1)
+ output_prio =
+ static_cast<int32_t>(ceil(output_prio / sqrt(static_cast<double>(bo.outputs.size()))));
+ prio += 2 * output_prio;
+
+ // If building consumes some wares, multiply with current statistics of all
+ // other buildings of this type to avoid constructing buildings where already
+ // some are running on low resources.
+ // Else at least add a part of the stats t the calculation.
+ if (!bo.inputs.empty()) {
+ prio *= bo.current_stats;
+ prio /= 100;
+ } else
+ prio = ((prio * bo.current_stats) / 100) + (prio / 2);
+
+ return prio;
+}
+
+void DefaultAI::consider_productionsite_influence(BuildableField& field,
+ Coords coords,
+ const BuildingObserver& bo) {
+ if (bo.space_consumer and game().map().calc_distance(coords, field.coords) < 4)
+ ++field.space_consumers_nearby;
+
+ for (size_t i = 0; i < bo.inputs.size(); ++i)
+ ++field.consumers_nearby.at(bo.inputs.at(i));
+ for (size_t i = 0; i < bo.outputs.size(); ++i)
+ ++field.producers_nearby.at(bo.outputs.at(i));
+}
/// \returns the economy observer containing \arg economy
-EconomyObserver * DefaultAI::get_economy_observer(Economy & economy)
-{
- for
- (std::list<EconomyObserver *>::iterator i = economies.begin();
- i != economies.end();
- ++i)
- if (&(*i)->economy == &economy)
- return *i;
-
- economies.push_front (new EconomyObserver(economy));
-
- return economies.front();
+EconomyObserver* DefaultAI::get_economy_observer(Economy& economy) {
+ for (std::list<EconomyObserver*>::iterator i = economies.begin(); i != economies.end(); ++i)
+ if (&(*i)->economy == &economy)
+ return *i;
+
+ economies.push_front(new EconomyObserver(economy));
+
+ return economies.front();
}
/// \returns the building observer
-BuildingObserver & DefaultAI::get_building_observer(char const * const name)
-{
- if (tribe == 0)
- late_initialization();
-
- for (uint32_t i = 0; i < buildings.size(); ++i)
- if (!strcmp(buildings.at(i).name, name))
- return buildings.at(i);
-
- throw wexception("Help: I do not know what to do with a %s", name);
+BuildingObserver& DefaultAI::get_building_observer(char const* const name) {
+ if (tribe == 0)
+ late_initialization();
+
+ for (uint32_t i = 0; i < buildings.size(); ++i)
+ if (!strcmp(buildings.at(i).name, name))
+ return buildings.at(i);
+
+ throw wexception("Help: I do not know what to do with a %s", name);
}
-
/// this is called whenever we gain ownership of a PlayerImmovable
-void DefaultAI::gain_immovable(PlayerImmovable & pi)
-{
- if (upcast(Building, building, &pi))
- gain_building (*building);
- else if (upcast(Flag const, flag, &pi))
- new_flags.push_back (flag);
- else if (upcast(Road const, road, &pi))
- roads .push_front(road);
+void DefaultAI::gain_immovable(PlayerImmovable& pi) {
+ if (upcast(Building, building, &pi))
+ gain_building(*building);
+ else if (upcast(Flag const, flag, &pi))
+ new_flags.push_back(flag);
+ else if (upcast(Road const, road, &pi))
+ roads.push_front(road);
}
/// this is called whenever we lose ownership of a PlayerImmovable
-void DefaultAI::lose_immovable(const PlayerImmovable & pi)
-{
- if (upcast(Building const, building, &pi))
- lose_building (*building);
- else if (upcast(Flag const, flag, &pi)) {
- container_iterate_const(std::list<EconomyObserver *>, economies, i)
- container_iterate(std::list<Flag const *>, (*i.current)->flags, j)
- if (*j.current == flag) {
- (*i.current)->flags.erase (j.current);
- return;
- }
- container_iterate(std::list<Flag const *>, new_flags, i)
- if (*i.current == flag) {
- new_flags.erase(i.current);
- return;
- }
- } else if (upcast(Road const, road, &pi))
- roads.remove (road);
+void DefaultAI::lose_immovable(const PlayerImmovable& pi) {
+ if (upcast(Building const, building, &pi))
+ lose_building(*building);
+ else if (upcast(Flag const, flag, &pi)) {
+ container_iterate_const(std::list<EconomyObserver*>, economies, i)
+ container_iterate(std::list<Flag const*>, (*i.current)->flags, j)
+ if (*j.current == flag) {
+ (*i.current)->flags.erase(j.current);
+ return;
+ }
+ container_iterate(std::list<Flag const*>, new_flags, i)
+ if (*i.current == flag) {
+ new_flags.erase(i.current);
+ return;
+ }
+ } else if (upcast(Road const, road, &pi))
+ roads.remove(road);
}
/// this is called whenever we gain a new building
-void DefaultAI::gain_building(Building & b)
-{
- BuildingObserver & bo = get_building_observer(b.name().c_str());
-
- if (bo.type == BuildingObserver::CONSTRUCTIONSITE) {
- BuildingObserver & target_bo =
- get_building_observer
- (ref_cast<ConstructionSite, Building>(b)
- .building().name().c_str());
- ++target_bo.cnt_under_construction;
- ++total_constructionsites;
- // Let defaultAI try to directly connect the constructionsite
- next_road_due = game().get_gametime();
- }
- else {
- ++bo.cnt_built;
-
- if (bo.type == BuildingObserver::PRODUCTIONSITE) {
- productionsites.push_back (ProductionSiteObserver());
- productionsites.back().site = &ref_cast<ProductionSite, Building>(b);
- productionsites.back().bo = &bo;
- productionsites.back().builttime = game().get_gametime();
- productionsites.back().statszero = 0;
-
- for (uint32_t i = 0; i < bo.outputs.size(); ++i)
- ++wares.at(bo.outputs.at(i)).producers;
-
- for (uint32_t i = 0; i < bo.inputs.size(); ++i)
- ++wares.at(bo.inputs.at(i)).consumers;
- } else if (bo.type == BuildingObserver::MINE) {
- mines.push_back (ProductionSiteObserver());
- mines.back().site = &ref_cast<ProductionSite, Building>(b);
- mines.back().bo = &bo;
-
- for (uint32_t i = 0; i < bo.outputs.size(); ++i)
- ++wares.at(bo.outputs.at(i)).producers;
-
- for (uint32_t i = 0; i < bo.inputs.size(); ++i)
- ++wares.at(bo.inputs.at(i)).consumers;
- } else if (bo.type == BuildingObserver::MILITARYSITE) {
- militarysites.push_back (MilitarySiteObserver());
- militarysites.back().site = &ref_cast<MilitarySite, Building>(b);
- militarysites.back().bo = &bo;
- militarysites.back().checks = bo.desc->get_size();
- } else if (bo.type == BuildingObserver::WAREHOUSE)
- ++numof_warehouses;
- }
+void DefaultAI::gain_building(Building& b) {
+ BuildingObserver& bo = get_building_observer(b.name().c_str());
+
+ if (bo.type == BuildingObserver::CONSTRUCTIONSITE) {
+ BuildingObserver& target_bo =
+ get_building_observer(ref_cast<ConstructionSite, Building>(b).building().name().c_str());
+ ++target_bo.cnt_under_construction;
+ ++total_constructionsites;
+ // Let defaultAI try to directly connect the constructionsite
+ next_road_due = game().get_gametime();
+ } else {
+ ++bo.cnt_built;
+
+ if (bo.type == BuildingObserver::PRODUCTIONSITE) {
+ productionsites.push_back(ProductionSiteObserver());
+ productionsites.back().site = &ref_cast<ProductionSite, Building>(b);
+ productionsites.back().bo = &bo;
+ productionsites.back().builttime = game().get_gametime();
+ productionsites.back().statszero = 0;
+
+ for (uint32_t i = 0; i < bo.outputs.size(); ++i)
+ ++wares.at(bo.outputs.at(i)).producers;
+
+ for (uint32_t i = 0; i < bo.inputs.size(); ++i)
+ ++wares.at(bo.inputs.at(i)).consumers;
+ } else if (bo.type == BuildingObserver::MINE) {
+ mines.push_back(ProductionSiteObserver());
+ mines.back().site = &ref_cast<ProductionSite, Building>(b);
+ mines.back().bo = &bo;
+
+ for (uint32_t i = 0; i < bo.outputs.size(); ++i)
+ ++wares.at(bo.outputs.at(i)).producers;
+
+ for (uint32_t i = 0; i < bo.inputs.size(); ++i)
+ ++wares.at(bo.inputs.at(i)).consumers;
+ } else if (bo.type == BuildingObserver::MILITARYSITE) {
+ militarysites.push_back(MilitarySiteObserver());
+ militarysites.back().site = &ref_cast<MilitarySite, Building>(b);
+ militarysites.back().bo = &bo;
+ militarysites.back().checks = bo.desc->get_size();
+ } else if (bo.type == BuildingObserver::WAREHOUSE)
+ ++numof_warehouses;
+ }
}
/// this is called whenever we lose a building
-void DefaultAI::lose_building(const Building & b)
-{
- BuildingObserver & bo = get_building_observer(b.name().c_str());
-
- if (bo.type == BuildingObserver::CONSTRUCTIONSITE) {
- BuildingObserver & target_bo =
- get_building_observer
- (ref_cast<ConstructionSite const, Building const>(b)
- .building().name().c_str());
- --target_bo.cnt_under_construction;
- --total_constructionsites;
- } else {
- --bo.cnt_built;
-
- if (bo.type == BuildingObserver::PRODUCTIONSITE) {
- for
- (std::list<ProductionSiteObserver>::iterator i =
- productionsites.begin();
- i != productionsites.end();
- ++i)
- if (i->site == &b) {
- productionsites.erase(i);
- break;
- }
-
- for (uint32_t i = 0; i < bo.outputs.size(); ++i)
- --wares.at(bo.outputs.at(i)).producers;
-
- for (uint32_t i = 0; i < bo.inputs.size(); ++i)
- --wares.at(bo.inputs.at(i)).consumers;
- } else if (bo.type == BuildingObserver::MINE) {
- for
- (std::list<ProductionSiteObserver>::iterator i =
- mines.begin();
- i != mines.end();
- ++i)
- if (i->site == &b) {
- mines.erase(i);
- break;
- }
-
- for (uint32_t i = 0; i < bo.outputs.size(); ++i)
- --wares.at(bo.outputs.at(i)).producers;
-
- for (uint32_t i = 0; i < bo.inputs.size(); ++i)
- --wares.at(bo.inputs.at(i)).consumers;
- } else if (bo.type == BuildingObserver::MILITARYSITE) {
- for
- (std::list<MilitarySiteObserver>::iterator i =
- militarysites.begin();
- i != militarysites.end();
- ++i)
- if (i->site == &b) {
- militarysites.erase(i);
- break;
- }
- } else if (bo.type == BuildingObserver::WAREHOUSE) {
- assert(numof_warehouses > 0);
- --numof_warehouses;
- }
- }
- m_buildable_changed = true;
- m_mineable_changed = true;
+void DefaultAI::lose_building(const Building& b) {
+ BuildingObserver& bo = get_building_observer(b.name().c_str());
+
+ if (bo.type == BuildingObserver::CONSTRUCTIONSITE) {
+ BuildingObserver& target_bo = get_building_observer(
+ ref_cast<ConstructionSite const, Building const>(b).building().name().c_str());
+ --target_bo.cnt_under_construction;
+ --total_constructionsites;
+ } else {
+ --bo.cnt_built;
+
+ if (bo.type == BuildingObserver::PRODUCTIONSITE) {
+ for (std::list<ProductionSiteObserver>::iterator i = productionsites.begin();
+ i != productionsites.end();
+ ++i)
+ if (i->site == &b) {
+ productionsites.erase(i);
+ break;
+ }
+
+ for (uint32_t i = 0; i < bo.outputs.size(); ++i)
+ --wares.at(bo.outputs.at(i)).producers;
+
+ for (uint32_t i = 0; i < bo.inputs.size(); ++i)
+ --wares.at(bo.inputs.at(i)).consumers;
+ } else if (bo.type == BuildingObserver::MINE) {
+ for (std::list<ProductionSiteObserver>::iterator i = mines.begin(); i != mines.end(); ++i)
+ if (i->site == &b) {
+ mines.erase(i);
+ break;
+ }
+
+ for (uint32_t i = 0; i < bo.outputs.size(); ++i)
+ --wares.at(bo.outputs.at(i)).producers;
+
+ for (uint32_t i = 0; i < bo.inputs.size(); ++i)
+ --wares.at(bo.inputs.at(i)).consumers;
+ } else if (bo.type == BuildingObserver::MILITARYSITE) {
+ for (std::list<MilitarySiteObserver>::iterator i = militarysites.begin();
+ i != militarysites.end();
+ ++i)
+ if (i->site == &b) {
+ militarysites.erase(i);
+ break;
+ }
+ } else if (bo.type == BuildingObserver::WAREHOUSE) {
+ assert(numof_warehouses > 0);
+ --numof_warehouses;
+ }
+ }
+ m_buildable_changed = true;
+ m_mineable_changed = true;
}
-
/// Checks that supply line exists for given building.
/// Recurcsively verify that all inputs have a producer.
// TODO: this function leads to periodic freezes of ~1 second on big games on my system.
// TODO: It needs profiling and optimization.
-bool DefaultAI::check_supply(const BuildingObserver & bo)
-{
- size_t supplied = 0;
- container_iterate_const(std::vector<int16_t>, bo.inputs, i)
- container_iterate_const(std::vector<BuildingObserver>, buildings, j)
- if
- (j.current->cnt_built &&
- std::find
- (j.current->outputs.begin(), j.current->outputs.end(),
- *i.current)
- !=
- j.current->outputs.end()
- &&
- check_supply(*j.current))
- {
- ++supplied;
- break;
- }
- return supplied == bo.inputs.size();
+bool DefaultAI::check_supply(const BuildingObserver& bo) {
+ size_t supplied = 0;
+ container_iterate_const(std::vector<int16_t>, bo.inputs, i)
+ container_iterate_const(std::vector<BuildingObserver>, buildings, j)
+ if (j.current->cnt_built &&
+ std::find(j.current->outputs.begin(), j.current->outputs.end(), *i.current) !=
+ j.current->outputs.end() &&
+ check_supply(*j.current)) {
+ ++supplied;
+ break;
+ }
+ return supplied == bo.inputs.size();
}
-
/**
* The defaultAi "considers" via this function whether to attack an
* enemy, if opposing military buildings are in sight. In case of an attack it
@@ -2283,84 +2101,82 @@
* \returns true, if attack was started.
*/
bool DefaultAI::consider_attack(int32_t const gametime) {
- // Only useable, if it owns at least one militarysite
- if (militarysites.empty())
- return false;
-
- Map & map = game().map();
- uint16_t const pn = player_number();
-
- // Check next militarysite
- MilitarySite * ms = militarysites.front().site;
- uint32_t const vision = ms->vision_range();
- FCoords f = map.get_fcoords(ms->get_position());
-
- Building * target = ms; // dummy initialisation to silence the compiler
- int32_t chance = 0;
- uint32_t attackers = 0;
- uint8_t retreat = ms->owner().get_retreat_percentage();
-
- // Search in a radius of the vision of the militarysite and collect
- // information about immovables in the area
- std::vector<ImmovableFound> immovables;
- map.find_immovables
- (Area<FCoords>(f, vision), &immovables, FindImmovableAttackable());
-
- for (uint32_t j = 0; j < immovables.size(); ++j)
- if (upcast(MilitarySite, bld, immovables.at(j).object)) {
- if (!player->is_hostile(bld->owner()))
- continue;
- if (bld->canAttack()) {
- int32_t ta = player->findAttackSoldiers(bld->base_flag());
- if (type == NORMAL)
- ta = ta * 2 / 3;
- if (ta < 1)
- continue;
-
- int32_t const tc = ta - bld->presentSoldiers().size();
- if (tc > chance) {
- target = bld;
- chance = tc;
- attackers = ta;
- }
- }
- } else if (upcast(Warehouse, wh, immovables.at(j).object)) {
- if (!player->is_hostile(wh->owner()))
- continue;
- if (wh->canAttack()) {
- int32_t ta = player->findAttackSoldiers(wh->base_flag());
- if (ta < 1)
- continue;
-
- // extra priority push!
- int32_t tc = ta * 2;
- if (tc > chance) {
- target = wh;
- chance = tc;
- attackers = ta;
- }
- }
- }
-
- // Reenque militarysite at the end of list
- militarysites.push_back(militarysites.front());
- militarysites.pop_front();
-
- // Return if chance to win is too low
- if (chance < 3) {
- next_attack_consideration_due = gametime % 7 * 1000 + gametime;
- return false;
- }
-
- if (ms->owner().is_retreat_change_allowed()) {
- // \todo Player is allowed to modify his retreat value
- }
-
- // Attack the selected target.
- game().send_player_enemyflagaction
- (target->base_flag(), pn, attackers, retreat);
-
- // Do not attack again too soon - returning soldiers must get healed first.
- next_attack_consideration_due = (gametime % 51 + 10) * 1000 + gametime;
- return true;
+ // Only useable, if it owns at least one militarysite
+ if (militarysites.empty())
+ return false;
+
+ Map& map = game().map();
+ uint16_t const pn = player_number();
+
+ // Check next militarysite
+ MilitarySite* ms = militarysites.front().site;
+ uint32_t const vision = ms->vision_range();
+ FCoords f = map.get_fcoords(ms->get_position());
+
+ Building* target = ms; // dummy initialisation to silence the compiler
+ int32_t chance = 0;
+ uint32_t attackers = 0;
+ uint8_t retreat = ms->owner().get_retreat_percentage();
+
+ // Search in a radius of the vision of the militarysite and collect
+ // information about immovables in the area
+ std::vector<ImmovableFound> immovables;
+ map.find_immovables(Area<FCoords>(f, vision), &immovables, FindImmovableAttackable());
+
+ for (uint32_t j = 0; j < immovables.size(); ++j)
+ if (upcast(MilitarySite, bld, immovables.at(j).object)) {
+ if (!player->is_hostile(bld->owner()))
+ continue;
+ if (bld->canAttack()) {
+ int32_t ta = player->findAttackSoldiers(bld->base_flag());
+ if (type == NORMAL)
+ ta = ta * 2 / 3;
+ if (ta < 1)
+ continue;
+
+ int32_t const tc = ta - bld->presentSoldiers().size();
+ if (tc > chance) {
+ target = bld;
+ chance = tc;
+ attackers = ta;
+ }
+ }
+ } else if (upcast(Warehouse, wh, immovables.at(j).object)) {
+ if (!player->is_hostile(wh->owner()))
+ continue;
+ if (wh->canAttack()) {
+ int32_t ta = player->findAttackSoldiers(wh->base_flag());
+ if (ta < 1)
+ continue;
+
+ // extra priority push!
+ int32_t tc = ta * 2;
+ if (tc > chance) {
+ target = wh;
+ chance = tc;
+ attackers = ta;
+ }
+ }
+ }
+
+ // Reenque militarysite at the end of list
+ militarysites.push_back(militarysites.front());
+ militarysites.pop_front();
+
+ // Return if chance to win is too low
+ if (chance < 3) {
+ next_attack_consideration_due = gametime % 7 * 1000 + gametime;
+ return false;
+ }
+
+ if (ms->owner().is_retreat_change_allowed()) {
+ // \todo Player is allowed to modify his retreat value
+ }
+
+ // Attack the selected target.
+ game().send_player_enemyflagaction(target->base_flag(), pn, attackers, retreat);
+
+ // Do not attack again too soon - returning soldiers must get healed first.
+ next_attack_consideration_due = (gametime % 51 + 10) * 1000 + gametime;
+ return true;
}
=== modified file 'src/ai/defaultai.h'
--- src/ai/defaultai.h 2013-03-04 00:52:03 +0000
+++ src/ai/defaultai.h 2013-05-18 05:56:27 +0000
@@ -67,132 +67,126 @@
*
*/
struct DefaultAI : Computer_Player {
- DefaultAI(Widelands::Game &, const Widelands::Player_Number, uint8_t);
- ~DefaultAI();
- virtual void think ();
-
- virtual void receive(const Widelands::NoteImmovable &);
- virtual void receive(const Widelands::NoteFieldPossession &);
-
- enum {
- AGGRESSIVE = 2,
- NORMAL = 1,
- DEFENSIVE = 0,
- };
-
- /// Implementation for Aggressive
- struct AggressiveImpl : public Computer_Player::Implementation {
- AggressiveImpl() {name = _("Aggressive");}
- Computer_Player * instantiate
- (Widelands::Game & game, Widelands::Player_Number const p) const
- {
- return new DefaultAI(game, p, AGGRESSIVE);
- }
- };
-
- struct NormalImpl : public Computer_Player::Implementation {
- NormalImpl() {name = _("Normal");}
- Computer_Player * instantiate
- (Widelands::Game & game, Widelands::Player_Number const p) const
- {
- return new DefaultAI(game, p, NORMAL);
- }
- };
-
- struct DefensiveImpl : public Computer_Player::Implementation {
- DefensiveImpl() {name = _("Defensive");}
- Computer_Player * instantiate
- (Widelands::Game & game, Widelands::Player_Number const p) const
- {
- return new DefaultAI(game, p, DEFENSIVE);
- }
- };
-
- static AggressiveImpl aggressiveImpl;
- static NormalImpl normalImpl;
- static DefensiveImpl defensiveImpl;
-
-private:
- void late_initialization ();
-
- void update_all_buildable_fields (int32_t);
- void update_all_mineable_fields (int32_t);
- void update_all_not_buildable_fields ();
-
- void update_buildable_field(BuildableField &, uint16_t = 6, bool = false);
- void update_mineable_field (MineableField &);
-
- void update_productionsite_stats(int32_t);
-
- bool construct_building (int32_t);
- bool construct_roads (int32_t);
- bool improve_roads (int32_t);
-
- bool improve_transportation_ways (const Widelands::Flag &);
- bool connect_flag_to_another_economy (const Widelands::Flag &);
-
- bool check_economies ();
- bool check_productionsites (int32_t);
- bool check_mines (int32_t);
- bool check_militarysites (int32_t);
-
- int32_t recalc_with_border_range(const BuildableField &, int32_t);
- int32_t calculate_need_for_ps(BuildingObserver &, int32_t);
-
- void consider_productionsite_influence
- (BuildableField &, Widelands::Coords, const BuildingObserver &);
-
- EconomyObserver * get_economy_observer (Widelands::Economy &);
- BuildingObserver & get_building_observer(char const *);
-
- void gain_immovable (Widelands::PlayerImmovable &);
- void lose_immovable (const Widelands::PlayerImmovable &);
- void gain_building (Widelands::Building &);
- void lose_building (const Widelands::Building &);
-
- bool check_supply (const BuildingObserver &);
-
- bool consider_attack (int32_t);
-
-
-private:
- // Variables of default AI
- uint8_t type;
-
- bool m_buildable_changed;
- bool m_mineable_changed;
-
- Widelands::Player * player;
- Widelands::Tribe_Descr const * tribe;
-
- std::vector<BuildingObserver> buildings;
- uint32_t total_constructionsites;
-
- std::list<Widelands::FCoords> unusable_fields;
- std::list<BuildableField *> buildable_fields;
- std::list<BlockedField> blocked_fields;
- std::list<MineableField *> mineable_fields;
- std::list<Widelands::Flag const *> new_flags;
- std::list<Widelands::Coords> flags_to_be_removed;
- std::list<Widelands::Road const *> roads;
- std::list<EconomyObserver *> economies;
- std::list<ProductionSiteObserver> productionsites;
- std::list<ProductionSiteObserver> mines;
- std::list<MilitarySiteObserver> militarysites;
-
- std::vector<WareObserver> wares;
-
- int32_t next_road_due;
- int32_t next_stats_update_due;
- int32_t next_construction_due;
- int32_t next_productionsite_check_due;
- int32_t next_mine_check_due;
- int32_t next_militarysite_check_due;
- int32_t next_attack_consideration_due;
- int32_t inhibit_road_building;
- int32_t time_of_last_construction;
-
- uint16_t numof_warehouses;
+ DefaultAI(Widelands::Game&, const Widelands::Player_Number, uint8_t);
+ ~DefaultAI();
+ virtual void think();
+
+ virtual void receive(const Widelands::NoteImmovable&);
+ virtual void receive(const Widelands::NoteFieldPossession&);
+
+ enum {
+ AGGRESSIVE = 2,
+ NORMAL = 1,
+ DEFENSIVE = 0,
+ };
+
+ /// Implementation for Aggressive
+ struct AggressiveImpl : public Computer_Player::Implementation {
+ AggressiveImpl() { name = _("Aggressive"); }
+ Computer_Player* instantiate(Widelands::Game& game, Widelands::Player_Number const p) const {
+ return new DefaultAI(game, p, AGGRESSIVE);
+ }
+ };
+
+ struct NormalImpl : public Computer_Player::Implementation {
+ NormalImpl() { name = _("Normal"); }
+ Computer_Player* instantiate(Widelands::Game& game, Widelands::Player_Number const p) const {
+ return new DefaultAI(game, p, NORMAL);
+ }
+ };
+
+ struct DefensiveImpl : public Computer_Player::Implementation {
+ DefensiveImpl() { name = _("Defensive"); }
+ Computer_Player* instantiate(Widelands::Game& game, Widelands::Player_Number const p) const {
+ return new DefaultAI(game, p, DEFENSIVE);
+ }
+ };
+
+ static AggressiveImpl aggressiveImpl;
+ static NormalImpl normalImpl;
+ static DefensiveImpl defensiveImpl;
+
+ private:
+ void late_initialization();
+
+ void update_all_buildable_fields(int32_t);
+ void update_all_mineable_fields(int32_t);
+ void update_all_not_buildable_fields();
+
+ void update_buildable_field(BuildableField&, uint16_t = 6, bool = false);
+ void update_mineable_field(MineableField&);
+
+ void update_productionsite_stats(int32_t);
+
+ bool construct_building(int32_t);
+ bool construct_roads(int32_t);
+ bool improve_roads(int32_t);
+
+ bool improve_transportation_ways(const Widelands::Flag&);
+ bool connect_flag_to_another_economy(const Widelands::Flag&);
+
+ bool check_economies();
+ bool check_productionsites(int32_t);
+ bool check_mines(int32_t);
+ bool check_militarysites(int32_t);
+
+ int32_t recalc_with_border_range(const BuildableField&, int32_t);
+ int32_t calculate_need_for_ps(BuildingObserver&, int32_t);
+
+ void consider_productionsite_influence(BuildableField&,
+ Widelands::Coords,
+ const BuildingObserver&);
+
+ EconomyObserver* get_economy_observer(Widelands::Economy&);
+ BuildingObserver& get_building_observer(char const*);
+
+ void gain_immovable(Widelands::PlayerImmovable&);
+ void lose_immovable(const Widelands::PlayerImmovable&);
+ void gain_building(Widelands::Building&);
+ void lose_building(const Widelands::Building&);
+
+ bool check_supply(const BuildingObserver&);
+
+ bool consider_attack(int32_t);
+
+ private:
+ // Variables of default AI
+ uint8_t type;
+
+ bool m_buildable_changed;
+ bool m_mineable_changed;
+
+ Widelands::Player* player;
+ Widelands::Tribe_Descr const* tribe;
+
+ std::vector<BuildingObserver> buildings;
+ uint32_t total_constructionsites;
+
+ std::list<Widelands::FCoords> unusable_fields;
+ std::list<BuildableField*> buildable_fields;
+ std::list<BlockedField> blocked_fields;
+ std::list<MineableField*> mineable_fields;
+ std::list<Widelands::Flag const*> new_flags;
+ std::list<Widelands::Coords> flags_to_be_removed;
+ std::list<Widelands::Road const*> roads;
+ std::list<EconomyObserver*> economies;
+ std::list<ProductionSiteObserver> productionsites;
+ std::list<ProductionSiteObserver> mines;
+ std::list<MilitarySiteObserver> militarysites;
+
+ std::vector<WareObserver> wares;
+
+ int32_t next_road_due;
+ int32_t next_stats_update_due;
+ int32_t next_construction_due;
+ int32_t next_productionsite_check_due;
+ int32_t next_mine_check_due;
+ int32_t next_militarysite_check_due;
+ int32_t next_attack_consideration_due;
+ int32_t inhibit_road_building;
+ int32_t time_of_last_construction;
+
+ uint16_t numof_warehouses;
};
#endif
=== modified file 'src/align.cc'
--- src/align.cc 2013-02-10 14:55:10 +0000
+++ src/align.cc 2013-05-18 05:56:27 +0000
@@ -22,22 +22,21 @@
namespace UI {
void correct_for_align(Align align, uint32_t w, uint32_t h, Point* pt) {
- //Vertical Align
- if (align & (Align_VCenter | Align_Bottom)) {
- if (align & Align_VCenter)
- pt->y -= h / 2;
- else
- pt->y -= h;
- }
+ //Vertical Align
+ if (align & (Align_VCenter | Align_Bottom)) {
+ if (align & Align_VCenter)
+ pt->y -= h / 2;
+ else
+ pt->y -= h;
+ }
- //Horizontal Align
- if ((align & Align_Horizontal) != Align_Left) {
- if (align & Align_HCenter)
- pt->x -= w / 2;
- else if (align & Align_Right)
- pt->x -= w;
- }
+ //Horizontal Align
+ if ((align & Align_Horizontal) != Align_Left) {
+ if (align & Align_HCenter)
+ pt->x -= w / 2;
+ else if (align & Align_Right)
+ pt->x -= w;
+ }
}
} // namespace UI
-
=== modified file 'src/align.h'
--- src/align.h 2013-02-10 13:44:17 +0000
+++ src/align.h 2013-05-18 05:56:27 +0000
@@ -25,28 +25,28 @@
namespace UI {
enum Align {
- Align_Left = 0,
- Align_HCenter = 1,
- Align_Right = 2,
- Align_Horizontal = 3,
-
- Align_Top = 0,
- Align_VCenter = 4,
- Align_Bottom = 8,
- Align_Vertical = 12,
-
- Align_TopLeft = 0,
- Align_CenterLeft = Align_VCenter,
- Align_BottomLeft = Align_Bottom,
-
- Align_TopCenter = Align_HCenter,
- Align_Center = Align_HCenter|Align_VCenter,
- Align_BottomCenter = Align_HCenter|Align_Bottom,
-
- Align_TopRight = Align_Right,
- Align_CenterRight = Align_Right|Align_VCenter,
-
- Align_BottomRight = Align_Right|Align_Bottom,
+ Align_Left = 0,
+ Align_HCenter = 1,
+ Align_Right = 2,
+ Align_Horizontal = 3,
+
+ Align_Top = 0,
+ Align_VCenter = 4,
+ Align_Bottom = 8,
+ Align_Vertical = 12,
+
+ Align_TopLeft = 0,
+ Align_CenterLeft = Align_VCenter,
+ Align_BottomLeft = Align_Bottom,
+
+ Align_TopCenter = Align_HCenter,
+ Align_Center = Align_HCenter | Align_VCenter,
+ Align_BottomCenter = Align_HCenter | Align_Bottom,
+
+ Align_TopRight = Align_Right,
+ Align_CenterRight = Align_Right | Align_VCenter,
+
+ Align_BottomRight = Align_Right | Align_Bottom,
};
void correct_for_align(Align, uint32_t w, uint32_t h, Point* pt);
=== modified file 'src/backtrace.cc'
--- src/backtrace.cc 2012-02-15 21:25:34 +0000
+++ src/backtrace.cc 2013-05-18 05:56:27 +0000
@@ -26,21 +26,20 @@
#endif
#endif
+std::string get_backtrace() {
+ std::string result("Backtrace:\n");
+#ifndef WIN32
+#ifndef __APPLE__
#define BACKTRACE_STACKSIZE 24
-
-std::string get_backtrace() {
- std::string result("Backtrace:\n");
-#ifndef WIN32
-#ifndef __APPLE__
- void * stack[BACKTRACE_STACKSIZE];
- size_t size = backtrace(stack, BACKTRACE_STACKSIZE);
- char * * const list = backtrace_symbols(stack, size);
- for (char * const * it = list; size; --size, ++it) {
- result += *it;
- result += '\n';
- }
- free(list);
-#endif
-#endif
- return result;
+ void* stack[BACKTRACE_STACKSIZE];
+ size_t size = backtrace(stack, BACKTRACE_STACKSIZE);
+ char** const list = backtrace_symbols(stack, size);
+ for (char* const* it = list; size; --size, ++it) {
+ result += *it;
+ result += '\n';
+ }
+ free(list);
+#endif
+#endif
+ return result;
}
=== modified file 'src/build_info.h'
--- src/build_info.h 2013-01-11 15:33:12 +0000
+++ src/build_info.h 2013-05-18 05:56:27 +0000
@@ -6,11 +6,10 @@
///\return the build id which is automagically created from the checkout's
///revision number or the VERSION file
-const std::string & build_id();
+const std::string& build_id();
///\return the build type, which is set during compile time (either manually
///or to a default value)
-const std::string & build_type();
+const std::string& build_type();
#endif
-
=== modified file 'src/campvis.cc'
--- src/campvis.cc 2013-04-22 20:15:00 +0000
+++ src/campvis.cc 2013-05-18 05:56:27 +0000
@@ -30,163 +30,152 @@
/**
* Get the path of campaign visibility save-file
*/
-std::string Campaign_visibility_save::get_path()
-{
- std::string savepath = "save";
- g_fs->EnsureDirectoryExists(savepath); // Make sure save directory exists
- savepath += "/campvis"; // add the name of save-file
-
- // check if campaigns visibility-save is available
- if (!(g_fs->FileExists(savepath)))
- make_campvis(savepath);
-
- // check if campaigns visibility-save is up to date
- Profile ca(savepath.c_str());
-
- // 1st version of campvis had no global section
- if (!ca.get_section("global"))
- update_campvis(savepath);
- else {
- Section & ca_s = ca.get_safe_section("global");
- Profile cc("campaigns/cconfig");
- Section & cc_s = cc.get_safe_section("global");
- if (cc_s.get_int("version") > ca_s.get_int("version"))
- update_campvis(savepath);
- }
-
- return savepath;
+std::string Campaign_visibility_save::get_path() {
+ std::string savepath = "save";
+ g_fs->EnsureDirectoryExists(savepath); // Make sure save directory exists
+ savepath += "/campvis"; // add the name of save-file
+
+ // check if campaigns visibility-save is available
+ if (!(g_fs->FileExists(savepath)))
+ make_campvis(savepath);
+
+ // check if campaigns visibility-save is up to date
+ Profile ca(savepath.c_str());
+
+ // 1st version of campvis had no global section
+ if (!ca.get_section("global"))
+ update_campvis(savepath);
+ else {
+ Section& ca_s = ca.get_safe_section("global");
+ Profile cc("campaigns/cconfig");
+ Section& cc_s = cc.get_safe_section("global");
+ if (cc_s.get_int("version") > ca_s.get_int("version"))
+ update_campvis(savepath);
+ }
+
+ return savepath;
}
-
/**
* Create the campaign visibility save-file of the user
*/
-void Campaign_visibility_save::make_campvis(const std::string & savepath)
-{
- // Only prepare campvis-file -> data will be written via update_campvis
- Profile campvis(savepath.c_str());
- campvis.pull_section("global");
- campvis.pull_section("campaigns");
- campvis.pull_section("campmaps");
- campvis.write(savepath.c_str(), true);
+void Campaign_visibility_save::make_campvis(const std::string& savepath) {
+ // Only prepare campvis-file -> data will be written via update_campvis
+ Profile campvis(savepath.c_str());
+ campvis.pull_section("global");
+ campvis.pull_section("campaigns");
+ campvis.pull_section("campmaps");
+ campvis.write(savepath.c_str(), true);
- update_campvis(savepath);
+ update_campvis(savepath);
}
-
/**
* Update the campaign visibility save-file of the user
*/
-void Campaign_visibility_save::update_campvis(const std::string & savepath)
-{
- // Variable declaration
- int32_t i = 0;
- int32_t imap = 0;
- char csection[12];
- char number[4];
- std::string mapsection;
- std::string cms;
-
- // Prepare cconfig and campvis
- Profile cconfig("campaigns/cconfig");
- Section & cconf_s = cconfig.get_safe_section("global");
- Profile campvisr(savepath.c_str());
- Profile campvisw(savepath.c_str());
-
- // Write down global section
- campvisw.pull_section("global").set_int("version", cconf_s.get_int("version", 1));
-
- // Write down visibility of campaigns
- Section & campv_c = campvisr.get_safe_section("campaigns");
- Section & campv_m = campvisr.get_safe_section("campmaps");
- {
- Section & vis = campvisw.pull_section("campaigns");
- sprintf(csection, "campsect%i", i);
- char cvisible[12];
- char cnewvisi[12];
- while (cconf_s.get_string(csection)) {
- sprintf(cvisible, "campvisi%i", i);
- sprintf(cnewvisi, "cnewvisi%i", i);
- bool visible = cconf_s.get_bool(cvisible) || campv_c.get_bool(csection);
- if (!visible) {
- const char * newvisi = cconf_s.get_string(cnewvisi, "");
- if (sizeof(newvisi) > 1) {
- visible = campv_m.get_bool(newvisi, false) || campv_c.get_bool(newvisi, false);
- }
- }
- vis.set_bool(csection, visible);
- ++i;
- sprintf(csection, "campsect%i", i);
- }
- }
-
- // Write down visibility of campaign maps
- Section & vis = campvisw.pull_section("campmaps");
- i = 0;
-
- sprintf(csection, "campsect%i", i);
- while (cconf_s.get_string(csection)) {
- mapsection = cconf_s.get_string(csection);
-
- cms = mapsection;
- sprintf(number, "%02i", imap);
- cms += number;
-
- while (Section * const s = cconfig.get_section(cms.c_str())) {
- bool visible = s->get_bool("visible") || campv_m.get_bool(cms.c_str());
- if (!visible) {
- const char * newvisi = s->get_string("newvisi", "");
- if (sizeof(newvisi) > 1) {
- visible = campv_m.get_bool(newvisi, false) || campv_c.get_bool(newvisi, false);
- }
- }
- vis.set_bool (cms.c_str(), visible);
-
- ++imap;
- cms = mapsection;
- sprintf(number, "%02i", imap);
- cms += number;
- }
-
- ++i;
- sprintf(csection, "campsect%i", i);
- imap = 0;
- }
- campvisw.write(savepath.c_str(), true);
+void Campaign_visibility_save::update_campvis(const std::string& savepath) {
+ // Variable declaration
+ int32_t i = 0;
+ int32_t imap = 0;
+ char csection[12];
+ char number[4];
+ std::string mapsection;
+ std::string cms;
+
+ // Prepare cconfig and campvis
+ Profile cconfig("campaigns/cconfig");
+ Section& cconf_s = cconfig.get_safe_section("global");
+ Profile campvisr(savepath.c_str());
+ Profile campvisw(savepath.c_str());
+
+ // Write down global section
+ campvisw.pull_section("global").set_int("version", cconf_s.get_int("version", 1));
+
+ // Write down visibility of campaigns
+ Section& campv_c = campvisr.get_safe_section("campaigns");
+ Section& campv_m = campvisr.get_safe_section("campmaps");
+ {
+ Section& vis = campvisw.pull_section("campaigns");
+ sprintf(csection, "campsect%i", i);
+ char cvisible[12];
+ char cnewvisi[12];
+ while (cconf_s.get_string(csection)) {
+ sprintf(cvisible, "campvisi%i", i);
+ sprintf(cnewvisi, "cnewvisi%i", i);
+ bool visible = cconf_s.get_bool(cvisible) || campv_c.get_bool(csection);
+ if (!visible) {
+ const char* newvisi = cconf_s.get_string(cnewvisi, "");
+ if (sizeof(newvisi) > 1) {
+ visible = campv_m.get_bool(newvisi, false) || campv_c.get_bool(newvisi, false);
+ }
+ }
+ vis.set_bool(csection, visible);
+ ++i;
+ sprintf(csection, "campsect%i", i);
+ }
+ }
+
+ // Write down visibility of campaign maps
+ Section& vis = campvisw.pull_section("campmaps");
+ i = 0;
+
+ sprintf(csection, "campsect%i", i);
+ while (cconf_s.get_string(csection)) {
+ mapsection = cconf_s.get_string(csection);
+
+ cms = mapsection;
+ sprintf(number, "%02i", imap);
+ cms += number;
+
+ while (Section* const s = cconfig.get_section(cms.c_str())) {
+ bool visible = s->get_bool("visible") || campv_m.get_bool(cms.c_str());
+ if (!visible) {
+ const char* newvisi = s->get_string("newvisi", "");
+ if (sizeof(newvisi) > 1) {
+ visible = campv_m.get_bool(newvisi, false) || campv_c.get_bool(newvisi, false);
+ }
+ }
+ vis.set_bool(cms.c_str(), visible);
+
+ ++imap;
+ cms = mapsection;
+ sprintf(number, "%02i", imap);
+ cms += number;
+ }
+
+ ++i;
+ sprintf(csection, "campsect%i", i);
+ imap = 0;
+ }
+ campvisw.write(savepath.c_str(), true);
}
-
/**
* Set an campaign entry in campvis visible or invisible.
* If it doesn't exist, create it.
* \param entry entry to be changed
* \param visible should the map be visible?
*/
-void Campaign_visibility_save::set_campaign_visibility
- (const std::string & entry, bool visible)
-{
- std::string savepath = get_path();
- Profile campvis(savepath.c_str());
-
- campvis.pull_section("campaigns").set_bool(entry.c_str(), visible);
-
- campvis.write(savepath.c_str(), false);
+void Campaign_visibility_save::set_campaign_visibility(const std::string& entry, bool visible) {
+ std::string savepath = get_path();
+ Profile campvis(savepath.c_str());
+
+ campvis.pull_section("campaigns").set_bool(entry.c_str(), visible);
+
+ campvis.write(savepath.c_str(), false);
}
-
/**
* Set an campaignmap entry in campvis visible or invisible.
* If it doesn't exist, create it.
* \param entry entry to be changed
* \param visible should the map be visible?
*/
-void Campaign_visibility_save::set_map_visibility
- (const std::string & entry, bool visible)
-{
- std::string savepath = get_path();
- Profile campvis(savepath.c_str());
-
- campvis.pull_section("campmaps").set_bool(entry.c_str(), visible);
-
- campvis.write(savepath.c_str(), false);
+void Campaign_visibility_save::set_map_visibility(const std::string& entry, bool visible) {
+ std::string savepath = get_path();
+ Profile campvis(savepath.c_str());
+
+ campvis.pull_section("campmaps").set_bool(entry.c_str(), visible);
+
+ campvis.write(savepath.c_str(), false);
}
=== modified file 'src/campvis.h'
--- src/campvis.h 2013-02-10 19:36:24 +0000
+++ src/campvis.h 2013-05-18 05:56:27 +0000
@@ -24,16 +24,14 @@
#include <cstring>
#include <string>
-
struct Campaign_visibility_save {
- std::string get_path();
- void set_campaign_visibility(const std::string &, bool);
- void set_map_visibility (const std::string &, bool);
+ std::string get_path();
+ void set_campaign_visibility(const std::string&, bool);
+ void set_map_visibility(const std::string&, bool);
-private:
- void make_campvis (const std::string &);
- void update_campvis(const std::string &);
+ private:
+ void make_campvis(const std::string&);
+ void update_campvis(const std::string&);
};
-
#endif
=== modified file 'src/chat.cc'
--- src/chat.cc 2012-12-16 19:08:53 +0000
+++ src/chat.cc 2013-05-18 05:56:27 +0000
@@ -23,115 +23,108 @@
using namespace Widelands;
-std::string ChatMessage::toPrintable() const
-{
- std::string message = "<p font-color=#33ff33 font-size=9>";
-
- // Escape richtext characters
- // The goal of this code is two-fold:
- // 1. Assuming an honest game host, we want to prevent the ability of
- // clients to use richtext.
- // 2. Assuming a malicious host or meta server, we want to reduce the
- // likelihood that a bug in the richtext renderer can be exploited,
- // by restricting the set of allowed richtext commands.
- // Most notably, images are not allowed in richtext at all.
- //
- // Note that we do want host and meta server to send some richtext code,
- // as the ability to send formatted commands is nice for the usability
- // of meta server and dedicated servers, so we're treading a bit of a
- // fine line here.
- std::string sanitized;
- for (std::string::size_type pos = 0; pos < msg.size(); ++pos) {
- if (msg[pos] == '<') {
- if (playern < 0) {
- static const std::string good1 = "</p><p";
- static const std::string good2 = "<br>";
- if (!msg.compare(pos, good1.size(), good1)) {
- std::string::size_type nextclose = msg.find('>', pos + good1.size());
- if
- (nextclose != std::string::npos &&
- (nextclose == pos + good1.size() || msg[pos + good1.size()] == ' '))
- {
- sanitized += good1;
- pos += good1.size() - 1;
- continue;
- }
- } else if (!msg.compare(pos, good2.size(), good2)) {
- sanitized += good2;
- pos += good2.size() - 1;
- continue;
- }
- }
-
- sanitized += "<";
- } else {
- sanitized += msg[pos];
- }
- }
-
- // time calculation
- char ts[13];
- strftime(ts, sizeof(ts), "[%H:%M] </p>", localtime(&time));
- message += ts;
-
- message += "<p font-size=14 font-face=DejaVuSerif font-color=#";
- message += color();
-
- if (recipient.size() && sender.size()) {
- // Personal message handling
- if (sanitized.compare(0, 3, "/me")) {
- message += " font-decoration=underline>";
- message += sender;
- message += " @ ";
- message += recipient;
- message += ":</p><p font-size=14 font-face=DejaVuSerif> ";
- message += sanitized;
- } else {
- message += ">@";
- message += recipient;
- message += " >> </p><p font-size=14";
- message += " font-face=DejaVuSerif font-color=#";
- message += color();
- message += " font-style=italic> ";
- message += sender;
- message += sanitized.substr(3);
- }
- } else {
- // Normal messages handling
- if (not sanitized.compare(0, 3, "/me")) {
- message += " font-style=italic>-> ";
- if (sender.size())
- message += sender;
- else
- message += "***";
- message += sanitized.substr(3);
- } else if (sender.size()) {
- message += " font-decoration=underline>";
- message += sender;
- message += ":</p><p font-size=14 font-face=DejaVuSerif> ";
- message += sanitized;
- } else {
- message += " font-weight=bold>*** ";
- message += sanitized;
- }
- }
-
- // return the formated message
- return message + "<br></p>";
-}
-
-std::string ChatMessage::toPlainString() const
-{
- return sender + ": " + msg;
-}
-
-std::string ChatMessage::color() const
-{
- if ((playern >= 0) && playern < MAX_PLAYERS) {
- const RGBColor & clr = Player::Colors[playern];
- char buf[sizeof("ffffff")];
- snprintf(buf, sizeof(buf), "%.2x%.2x%.2x", clr.r, clr.g, clr.b);
- return buf;
- }
- return "999999";
+std::string ChatMessage::toPrintable() const {
+ std::string message = "<p font-color=#33ff33 font-size=9>";
+
+ // Escape richtext characters
+ // The goal of this code is two-fold:
+ // 1. Assuming an honest game host, we want to prevent the ability of
+ // clients to use richtext.
+ // 2. Assuming a malicious host or meta server, we want to reduce the
+ // likelihood that a bug in the richtext renderer can be exploited,
+ // by restricting the set of allowed richtext commands.
+ // Most notably, images are not allowed in richtext at all.
+ //
+ // Note that we do want host and meta server to send some richtext code,
+ // as the ability to send formatted commands is nice for the usability
+ // of meta server and dedicated servers, so we're treading a bit of a
+ // fine line here.
+ std::string sanitized;
+ for (std::string::size_type pos = 0; pos < msg.size(); ++pos) {
+ if (msg[pos] == '<') {
+ if (playern < 0) {
+ static const std::string good1 = "</p><p";
+ static const std::string good2 = "<br>";
+ if (!msg.compare(pos, good1.size(), good1)) {
+ std::string::size_type nextclose = msg.find('>', pos + good1.size());
+ if (nextclose != std::string::npos &&
+ (nextclose == pos + good1.size() || msg[pos + good1.size()] == ' ')) {
+ sanitized += good1;
+ pos += good1.size() - 1;
+ continue;
+ }
+ } else if (!msg.compare(pos, good2.size(), good2)) {
+ sanitized += good2;
+ pos += good2.size() - 1;
+ continue;
+ }
+ }
+
+ sanitized += "<";
+ } else {
+ sanitized += msg[pos];
+ }
+ }
+
+ // time calculation
+ char ts[13];
+ strftime(ts, sizeof(ts), "[%H:%M] </p>", localtime(&time));
+ message += ts;
+
+ message += "<p font-size=14 font-face=DejaVuSerif font-color=#";
+ message += color();
+
+ if (recipient.size() && sender.size()) {
+ // Personal message handling
+ if (sanitized.compare(0, 3, "/me")) {
+ message += " font-decoration=underline>";
+ message += sender;
+ message += " @ ";
+ message += recipient;
+ message += ":</p><p font-size=14 font-face=DejaVuSerif> ";
+ message += sanitized;
+ } else {
+ message += ">@";
+ message += recipient;
+ message += " >> </p><p font-size=14";
+ message += " font-face=DejaVuSerif font-color=#";
+ message += color();
+ message += " font-style=italic> ";
+ message += sender;
+ message += sanitized.substr(3);
+ }
+ } else {
+ // Normal messages handling
+ if (not sanitized.compare(0, 3, "/me")) {
+ message += " font-style=italic>-> ";
+ if (sender.size())
+ message += sender;
+ else
+ message += "***";
+ message += sanitized.substr(3);
+ } else if (sender.size()) {
+ message += " font-decoration=underline>";
+ message += sender;
+ message += ":</p><p font-size=14 font-face=DejaVuSerif> ";
+ message += sanitized;
+ } else {
+ message += " font-weight=bold>*** ";
+ message += sanitized;
+ }
+ }
+
+ // return the formated message
+ return message + "<br></p>";
+}
+
+std::string ChatMessage::toPlainString() const { return sender + ": " + msg; }
+
+std::string ChatMessage::color() const {
+ if ((playern >= 0) && playern < MAX_PLAYERS) {
+ const RGBColor& clr = Player::Colors[playern];
+ char buf[sizeof("ffffff")];
+ snprintf(buf, sizeof(buf), "%.2x%.2x%.2x", clr.r, clr.g, clr.b);
+ return buf;
+ }
+ return "999999";
}
=== modified file 'src/chat.h'
--- src/chat.h 2013-02-10 19:36:24 +0000
+++ src/chat.h 2013-05-18 05:56:27 +0000
@@ -29,64 +29,61 @@
* Represents one chat message.
*/
struct ChatMessage {
- /**
- * The (real-)time at which the message was received.
- */
- time_t time;
-
- /**
- * The playercolor. Used to colorize the senders name;
- * negative numbers indicate system messages for which richtext is
- * allowed.
- */
- int16_t playern;
-
- /**
- * A string identifying the sender of the message.
- *
- * This string is empty for system-generated messages.
- *
- * \note This is a string instead of an ID because the backlog of
- * chat messages might contain chat from a player who has since left
- * the game.
- */
- std::string sender;
-
- /**
- * A string identifying the recipient of the message.
- *
- * This string should only be filled for personal messages.
- *
- * \note This is a string instead of an ID because the backlog of
- * chat messages might contain chat from a player who has since left
- * the game.
- */
- std::string recipient;
-
- /**
- * The actual chat message
- */
- std::string msg;
-
-
- /**
- * \return a richtext string that can be displayed to the user.
- */
- std::string toPrintable() const;
-
- /**
- * \return a plain string containing the sender + message.
- */
- std::string toPlainString() const;
-
-
- /**
- * \returns the color of the sender
- */
- std::string color() const;
+ /**
+ * The (real-)time at which the message was received.
+ */
+ time_t time;
+
+ /**
+ * The playercolor. Used to colorize the senders name;
+ * negative numbers indicate system messages for which richtext is
+ * allowed.
+ */
+ int16_t playern;
+
+ /**
+ * A string identifying the sender of the message.
+ *
+ * This string is empty for system-generated messages.
+ *
+ * \note This is a string instead of an ID because the backlog of
+ * chat messages might contain chat from a player who has since left
+ * the game.
+ */
+ std::string sender;
+
+ /**
+ * A string identifying the recipient of the message.
+ *
+ * This string should only be filled for personal messages.
+ *
+ * \note This is a string instead of an ID because the backlog of
+ * chat messages might contain chat from a player who has since left
+ * the game.
+ */
+ std::string recipient;
+
+ /**
+ * The actual chat message
+ */
+ std::string msg;
+
+ /**
+ * \return a richtext string that can be displayed to the user.
+ */
+ std::string toPrintable() const;
+
+ /**
+ * \return a plain string containing the sender + message.
+ */
+ std::string toPlainString() const;
+
+ /**
+ * \returns the color of the sender
+ */
+ std::string color() const;
};
-
/**
* Provides the chatting interface during a game.
*
@@ -96,27 +93,25 @@
* time a new message is received.
*/
struct ChatProvider : public Widelands::NoteSender<ChatMessage> {
- virtual ~ChatProvider() {}
-
- /**
- * Send the given chat message.
- *
- * The message may or may not appear in subsequent calls to \ref getMessages.
- */
- virtual void send(const std::string &) = 0;
-
- /**
- * \return a (chronological) list of received chat messages.
- * This list need not be stable or monotonic. In other words,
- * subsequent calls to this functions may return a smaller or
- * greater number of chat messages.
- */
- virtual const std::vector<ChatMessage> & getMessages() const = 0;
-
-protected:
- void send(const ChatMessage & c) {
- Widelands::NoteSender<ChatMessage>::send(c);
- }
+ virtual ~ChatProvider() {}
+
+ /**
+ * Send the given chat message.
+ *
+ * The message may or may not appear in subsequent calls to \ref getMessages.
+ */
+ virtual void send(const std::string&) = 0;
+
+ /**
+ * \return a (chronological) list of received chat messages.
+ * This list need not be stable or monotonic. In other words,
+ * subsequent calls to this functions may return a smaller or
+ * greater number of chat messages.
+ */
+ virtual const std::vector<ChatMessage>& getMessages() const = 0;
+
+ protected:
+ void send(const ChatMessage& c) { Widelands::NoteSender<ChatMessage>::send(c); }
};
#endif
=== modified file 'src/compile_assert.h'
--- src/compile_assert.h 2013-02-10 18:47:18 +0000
+++ src/compile_assert.h 2013-05-18 05:56:27 +0000
@@ -22,7 +22,7 @@
// about this shadowing the last assert. This is not too easy, so we use the
// line number - collisions are not that probable anymore.
// The concatenation magic is from: http://stackoverflow.com/a/1597129/200945
-#define TOKENPASTE(x, y) x ## y
+#define TOKENPASTE(x, y) x##y
#define TOKENPASTE2(x, y) TOKENPASTE(x, y)
#define compile_assert(x) typedef bool TOKENPASTE2(COMPILE_ASSERT_, __LINE__)[(x) ? 1 : -1]
#endif
=== modified file 'src/compile_diagnostics.h'
--- src/compile_diagnostics.h 2013-01-20 14:25:26 +0000
+++ src/compile_diagnostics.h 2013-05-18 05:56:27 +0000
@@ -25,14 +25,13 @@
* use in the middle of functions.
*/
#if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406
-# define GCC_DIAG_DO_PRAGMA(x) _Pragma (#x)
-# define GCC_DIAG_PRAGMA(x) GCC_DIAG_DO_PRAGMA(GCC diagnostic x)
-# define GCC_DIAG_OFF(x) GCC_DIAG_PRAGMA(push) \
- GCC_DIAG_PRAGMA(ignored x)
-# define GCC_DIAG_ON(x) GCC_DIAG_PRAGMA(pop)
+#define GCC_DIAG_DO_PRAGMA(x) _Pragma(#x)
+#define GCC_DIAG_PRAGMA(x) GCC_DIAG_DO_PRAGMA(GCC diagnostic x)
+#define GCC_DIAG_OFF(x) GCC_DIAG_PRAGMA(push) GCC_DIAG_PRAGMA(ignored x)
+#define GCC_DIAG_ON(x) GCC_DIAG_PRAGMA(pop)
#else
-# define GCC_DIAG_OFF(x)
-# define GCC_DIAG_ON(x)
+#define GCC_DIAG_OFF(x)
+#define GCC_DIAG_ON(x)
#endif
/* Macros for disabling Clang warnings and errors
@@ -40,18 +39,17 @@
* slightly modified.
*/
#ifdef __clang__
-# define CLANG_DIAG_DO_PRAGMA(x) _Pragma (#x)
+#define CLANG_DIAG_DO_PRAGMA(x) _Pragma(#x)
// _Pragma is unary operator #pragma ("")
-# define CLANG_DIAG_PRAGMA(x) CLANG_DIAG_DO_PRAGMA(clang diagnostic x)
-# define CLANG_DIAG_OFF(x) CLANG_DIAG_PRAGMA(push) \
- CLANG_DIAG_PRAGMA(ignored x)
+#define CLANG_DIAG_PRAGMA(x) CLANG_DIAG_DO_PRAGMA(clang diagnostic x)
+#define CLANG_DIAG_OFF(x) CLANG_DIAG_PRAGMA(push) CLANG_DIAG_PRAGMA(ignored x)
// For example: #pragma clang diagnostic ignored "-Wno-unused-variable"
-# define CLANG_DIAG_ON(x) CLANG_DIAG_PRAGMA(pop)
+#define CLANG_DIAG_ON(x) CLANG_DIAG_PRAGMA(pop)
// For example: #pragma clang diagnostic warning "-Wno-unused-variable"
-#else // Ensure these macros do nothing for other compilers.
-# define CLANG_DIAG_OFF(x)
-# define CLANG_DIAG_ON(x)
-# define CLANG_DIAG_PRAGMA(x)
+#else // Ensure these macros do nothing for other compilers.
+#define CLANG_DIAG_OFF(x)
+#define CLANG_DIAG_ON(x)
+#define CLANG_DIAG_PRAGMA(x)
#endif
#endif
=== modified file 'src/computer_player.cc'
--- src/computer_player.cc 2013-02-10 19:36:24 +0000
+++ src/computer_player.cc 2013-05-18 05:56:27 +0000
@@ -21,56 +21,45 @@
#include "ai/defaultai.h"
-Computer_Player::Computer_Player
- (Widelands::Game & g, Widelands::Player_Number const pid)
- : m_game(g), m_player_number(pid)
-{
-}
-
+Computer_Player::Computer_Player(Widelands::Game& g, Widelands::Player_Number const pid)
+ : m_game(g), m_player_number(pid) {}
struct EmptyAI : Computer_Player {
- EmptyAI(Widelands::Game & g, const Widelands::Player_Number pid)
- : Computer_Player(g, pid) {}
-
- void think() {}
-
- struct EmptyAIImpl : Implementation {
- EmptyAIImpl() {name = _("None");}
- Computer_Player * instantiate
- (Widelands::Game & g, Widelands::Player_Number const pid) const
- {
- return new EmptyAI(g, pid);
- }
- };
-
- static EmptyAIImpl implementation;
+ EmptyAI(Widelands::Game& g, const Widelands::Player_Number pid) : Computer_Player(g, pid) {}
+
+ void think() {}
+
+ struct EmptyAIImpl : Implementation {
+ EmptyAIImpl() { name = _("None"); }
+ Computer_Player* instantiate(Widelands::Game& g, Widelands::Player_Number const pid) const {
+ return new EmptyAI(g, pid);
+ }
+ };
+
+ static EmptyAIImpl implementation;
};
EmptyAI::EmptyAIImpl EmptyAI::implementation;
-const Computer_Player::ImplementationVector &
-Computer_Player::getImplementations()
-{
- static std::vector<Computer_Player::Implementation const *> impls;
-
- if (impls.empty()) {
- impls.push_back(&DefaultAI::aggressiveImpl);
- impls.push_back(&DefaultAI::normalImpl);
- impls.push_back(&DefaultAI::defensiveImpl);
- impls.push_back(&EmptyAI::implementation);
- }
-
- return impls;
+const Computer_Player::ImplementationVector& Computer_Player::getImplementations() {
+ static std::vector<Computer_Player::Implementation const*> impls;
+
+ if (impls.empty()) {
+ impls.push_back(&DefaultAI::aggressiveImpl);
+ impls.push_back(&DefaultAI::normalImpl);
+ impls.push_back(&DefaultAI::defensiveImpl);
+ impls.push_back(&EmptyAI::implementation);
+ }
+
+ return impls;
}
-const Computer_Player::Implementation * Computer_Player::getImplementation
- (const std::string & name)
-{
- const ImplementationVector & vec = getImplementations();
-
- container_iterate_const(ImplementationVector, vec, i)
- if ((*i.current)->name == name)
- return *i.current;
-
- return vec[0];
+const Computer_Player::Implementation* Computer_Player::getImplementation(const std::string& name) {
+ const ImplementationVector& vec = getImplementations();
+
+ container_iterate_const(ImplementationVector, vec, i)
+ if ((*i.current)->name == name)
+ return *i.current;
+
+ return vec[0];
}
=== modified file 'src/computer_player.h'
--- src/computer_player.h 2013-02-10 19:36:24 +0000
+++ src/computer_player.h 2013-05-18 05:56:27 +0000
@@ -31,49 +31,44 @@
* Instances of actual AI implementation can be created via the
* \ref Implementation interface.
*/
-struct Computer_Player :
- boost::noncopyable,
- Widelands::NoteReceiver<Widelands::NoteImmovable>,
- Widelands::NoteReceiver<Widelands::NoteFieldPossession>
-{
- Computer_Player(Widelands::Game &, const Widelands::Player_Number);
-
- virtual void think () = 0;
-
- virtual void receive(const Widelands::NoteImmovable &) {}
- virtual void receive(const Widelands::NoteFieldPossession &) {}
-
- Widelands::Game & game() const throw () {return m_game;}
- Widelands::Player_Number player_number() {return m_player_number;}
-
- /**
- * Interface to a concrete implementation, used to instantiate AIs.
- *
- * \see getImplementations()
- */
- struct Implementation {
- std::string name;
- virtual ~Implementation() {}
- virtual Computer_Player * instantiate
- (Widelands::Game &, Widelands::Player_Number) const = 0;
- };
- typedef
- std::vector<Computer_Player::Implementation const *>
- ImplementationVector;
-
- /**
- * Get a list of available AI implementations.
- */
- static const ImplementationVector & getImplementations();
-
- /**
- * Get the best matching implementation for this name.
- */
- static const Implementation * getImplementation(const std::string & name);
-
-private:
- Widelands::Game & m_game;
- Widelands::Player_Number const m_player_number;
+struct Computer_Player : boost::noncopyable,
+ Widelands::NoteReceiver<Widelands::NoteImmovable>,
+ Widelands::NoteReceiver<Widelands::NoteFieldPossession> {
+ Computer_Player(Widelands::Game&, const Widelands::Player_Number);
+
+ virtual void think() = 0;
+
+ virtual void receive(const Widelands::NoteImmovable&) {}
+ virtual void receive(const Widelands::NoteFieldPossession&) {}
+
+ Widelands::Game& game() const throw() { return m_game; }
+ Widelands::Player_Number player_number() { return m_player_number; }
+
+ /**
+ * Interface to a concrete implementation, used to instantiate AIs.
+ *
+ * \see getImplementations()
+ */
+ struct Implementation {
+ std::string name;
+ virtual ~Implementation() {}
+ virtual Computer_Player* instantiate(Widelands::Game&, Widelands::Player_Number) const = 0;
+ };
+ typedef std::vector<Computer_Player::Implementation const*> ImplementationVector;
+
+ /**
+ * Get a list of available AI implementations.
+ */
+ static const ImplementationVector& getImplementations();
+
+ /**
+ * Get the best matching implementation for this name.
+ */
+ static const Implementation* getImplementation(const std::string& name);
+
+ private:
+ Widelands::Game& m_game;
+ Widelands::Player_Number const m_player_number;
};
#endif
=== modified file 'src/constants.h'
--- src/constants.h 2013-02-28 15:55:51 +0000
+++ src/constants.h 2013-05-18 05:56:27 +0000
@@ -38,8 +38,8 @@
#define TEXTURE_HEIGHT TEXTURE_WIDTH
//@}
-#define XRES 800 ///< Fullscreen Menu Width
-#define YRES 600 ///< Fullscreen Menu Height
+#define XRES 800 ///< Fullscreen Menu Width
+#define YRES 600 ///< Fullscreen Menu Height
#define FALLBACK_GRAPHICS_WIDTH 640
#define FALLBACK_GRAPHICS_HEIGHT 480
@@ -48,22 +48,22 @@
/// \name Fonts
/// Font constants, defined including size
//@{
-#define UI_FONT_NAME_SERIF "DejaVuSerif.ttf"
-#define UI_FONT_NAME_SANS "DejaVuSans.ttf"
-#define UI_FONT_NAME_WIDELANDS "Widelands/Widelands.ttf"
+#define UI_FONT_NAME_SERIF "DejaVuSerif.ttf"
+#define UI_FONT_NAME_SANS "DejaVuSans.ttf"
+#define UI_FONT_NAME_WIDELANDS "Widelands/Widelands.ttf"
-#define UI_FONT_NAME UI_FONT_NAME_SERIF
-#define UI_FONT_NAME_NO_EXT "DejaVuSerif"
-#define UI_FONT_SIZE_BIG 22
-#define UI_FONT_SIZE_SMALL 14
+#define UI_FONT_NAME UI_FONT_NAME_SERIF
+#define UI_FONT_NAME_NO_EXT "DejaVuSerif"
+#define UI_FONT_SIZE_BIG 22
+#define UI_FONT_SIZE_SMALL 14
#define UI_FONT_SIZE_ULTRASMALL 10
-#define UI_FONT_BIG UI_FONT_NAME, UI_FONT_SIZE_BIG
-#define UI_FONT_SMALL UI_FONT_NAME, UI_FONT_SIZE_SMALL
-#define UI_FONT_ULTRASMALL UI_FONT_NAME, UI_FONT_SIZE_ULTRASMALL
+#define UI_FONT_BIG UI_FONT_NAME, UI_FONT_SIZE_BIG
+#define UI_FONT_SMALL UI_FONT_NAME, UI_FONT_SIZE_SMALL
+#define UI_FONT_ULTRASMALL UI_FONT_NAME, UI_FONT_SIZE_ULTRASMALL
-#define UI_FONT_TOOLTIP UI_FONT_SMALL
-#define PROSA_FONT UI_FONT_NAME_SERIF, 18
+#define UI_FONT_TOOLTIP UI_FONT_SMALL
+#define PROSA_FONT UI_FONT_NAME_SERIF, 18
//@}
/// \name Font colors
@@ -71,18 +71,18 @@
//@{
/// Global UI font color
-#define UI_FONT_CLR_FG RGBColor(255, 255, 0)
-#define UI_FONT_CLR_BG RGBColor(107, 87, 55)
+#define UI_FONT_CLR_FG RGBColor(255, 255, 0)
+#define UI_FONT_CLR_BG RGBColor(107, 87, 55)
#define UI_FONT_CLR_DISABLED RGBColor(127, 127, 127)
-#define UI_FONT_CLR_WARNING RGBColor(255, 22, 22)
+#define UI_FONT_CLR_WARNING RGBColor(255, 22, 22)
/// Prosa font color
-#define PROSA_FONT_CLR_FG RGBColor(255, 255, 0)
+#define PROSA_FONT_CLR_FG RGBColor(255, 255, 0)
/// Colors for good/ok/bad
-#define UI_FONT_CLR_BAD_HEX "ff0000"
-#define UI_FONT_CLR_OK_HEX "ffff00"
-#define UI_FONT_CLR_GOOD_HEX "325b1f"
+#define UI_FONT_CLR_BAD_HEX "ff0000"
+#define UI_FONT_CLR_OK_HEX "ffff00"
+#define UI_FONT_CLR_GOOD_HEX "325b1f"
//@}
/** \name Text colors
@@ -93,9 +93,9 @@
* backgrounds.
*/
//@{
-#define UI_FONT_BIG_CLR UI_FONT_CLR_FG, UI_FONT_CLR_BG
+#define UI_FONT_BIG_CLR UI_FONT_CLR_FG, UI_FONT_CLR_BG
/// small is used for ultrasmall, too
-#define UI_FONT_SMALL_CLR UI_FONT_CLR_FG, UI_FONT_CLR_BG
+#define UI_FONT_SMALL_CLR UI_FONT_CLR_FG, UI_FONT_CLR_BG
#define UI_FONT_TOOLTIP_CLR RGBColor(255, 255, 0)
//@}
@@ -108,7 +108,7 @@
//@{
#define WIDELANDS_LAN_DISCOVERY_PORT 7394
#define WIDELANDS_LAN_PROMOTION_PORT 7395
-#define WIDELANDS_PORT 7396
+#define WIDELANDS_PORT 7396
//@}
/// Maximum numbers of players in a game. The game logic code reserves 5 bits
@@ -123,7 +123,7 @@
/// Constants for user-defined SDL events that get handled by SDL's mainloop
//@{
enum {
- CHANGE_MUSIC
+ CHANGE_MUSIC
};
//@}
@@ -136,6 +136,6 @@
/// The size of the surface cache in bytes. This is the amount of graphics
/// memory widelands uses approximately. Note that not every Surface is also in
/// the cache, so the actual value will be different - but not by much.
-const uint32_t SURFACE_CACHE_SIZE = 150 << 20; // shifting converts to MB
+const uint32_t SURFACE_CACHE_SIZE = 150 << 20; // shifting converts to MB
#endif
=== modified file 'src/container_iterate.h'
--- src/container_iterate.h 2012-02-15 21:25:34 +0000
+++ src/container_iterate.h 2013-05-18 05:56:27 +0000
@@ -26,21 +26,22 @@
// for (wl_index_range<int> i(1, 10);i;++i)
// std::cout << i.current;
//
-template<typename T>
-struct wl_index_range
-{
- wl_index_range(const T & beginIndex, const T & endIndex) : current(beginIndex), end(endIndex) {}
- wl_index_range(const wl_index_range & r) : current(r.current), end(r.end) {}
- wl_index_range(T & r) : current(r.begin()), end(r.end()) {}
- T current;
- wl_index_range & operator++() {++current; return *this;}
- bool empty() const {return current == end;}
- operator bool() const {return empty() ? false : true;}
-private:
- T end;
+template <typename T> struct wl_index_range {
+ wl_index_range(const T& beginIndex, const T& endIndex) : current(beginIndex), end(endIndex) {}
+ wl_index_range(const wl_index_range& r) : current(r.current), end(r.end) {}
+ wl_index_range(T& r) : current(r.begin()), end(r.end()) {}
+ T current;
+ wl_index_range& operator++() {
+ ++current;
+ return *this;
+ }
+ bool empty() const { return current == end; }
+ operator bool() const { return empty() ? false : true; }
+
+ private:
+ T end;
};
-
// Helper structure for representing an iterator range in
// for loops.
// Usage:
@@ -48,25 +49,29 @@
// for (wl_range< std::vector<int> > i(v);i;++i)
// std::cout << *i;
//
-template<typename C>
-struct wl_range
-{
- wl_range
- (const typename C::iterator & first, const typename C::iterator & last) :
- current(first), end(last) {}
- wl_range(C & container) : current(container.begin()), end(container.end()) {}
- wl_range(const wl_range & r) : current(r.current), end(r.end) {}
- typename C::iterator current;
- wl_range & operator++() {++current; return *this;}
- wl_range<C> & advance() {++current; return *this;}
- bool empty() const {return current == end;}
- operator bool() const {return empty() ? false: true;}
- typename C::reference front() const {return *current;}
- typename C::reference operator*() const {return *current;}
- typename C::pointer operator->() const {return (&**this);}
- typename C::iterator get_end() {return end;}
-private:
- typename C::iterator end;
+template <typename C> struct wl_range {
+ wl_range(const typename C::iterator& first, const typename C::iterator& last)
+ : current(first), end(last) {}
+ wl_range(C& container) : current(container.begin()), end(container.end()) {}
+ wl_range(const wl_range& r) : current(r.current), end(r.end) {}
+ typename C::iterator current;
+ wl_range& operator++() {
+ ++current;
+ return *this;
+ }
+ wl_range<C>& advance() {
+ ++current;
+ return *this;
+ }
+ bool empty() const { return current == end; }
+ operator bool() const { return empty() ? false : true; }
+ typename C::reference front() const { return *current; }
+ typename C::reference operator*() const { return *current; }
+ typename C::pointer operator->() const { return (&**this); }
+ typename C::iterator get_end() { return end; }
+
+ private:
+ typename C::iterator end;
};
// Helper structure for representing an iterator range in
@@ -76,26 +81,29 @@
// for (wl_const_range< std::vector<int> > i(v);i;++i)
// std::cout << *i;
//
-template<typename C>
-struct wl_const_range
-{
- wl_const_range
- (const typename C::const_iterator & first,
- const typename C::const_iterator & last)
- : current(first), end(last) {}
- wl_const_range(const C & container) : current(container.begin()), end(container.end()) {}
- wl_const_range(const wl_const_range & r) : current(r.current), end(r.end) {}
- typename C::const_iterator current;
- wl_const_range & operator++() {++current; return *this;}
- wl_const_range<C> & advance() {++current; return *this;}
- bool empty() const {return current == end;}
- operator bool() const {return empty() ? false: true;}
- typename C::const_reference front() const {return *current;}
- typename C::const_reference operator*() const {return *current;}
- typename C::const_pointer operator->() const {return (&**this);}
- typename C::const_iterator get_end() {return end;}
-private:
- typename C::const_iterator end;
+template <typename C> struct wl_const_range {
+ wl_const_range(const typename C::const_iterator& first, const typename C::const_iterator& last)
+ : current(first), end(last) {}
+ wl_const_range(const C& container) : current(container.begin()), end(container.end()) {}
+ wl_const_range(const wl_const_range& r) : current(r.current), end(r.end) {}
+ typename C::const_iterator current;
+ wl_const_range& operator++() {
+ ++current;
+ return *this;
+ }
+ wl_const_range<C>& advance() {
+ ++current;
+ return *this;
+ }
+ bool empty() const { return current == end; }
+ operator bool() const { return empty() ? false : true; }
+ typename C::const_reference front() const { return *current; }
+ typename C::const_reference operator*() const { return *current; }
+ typename C::const_pointer operator->() const { return (&**this); }
+ typename C::const_iterator get_end() { return end; }
+
+ private:
+ typename C::const_iterator end;
};
// helper for erasing element in range so that range stays valid.
@@ -103,24 +111,13 @@
// Returns new range with updated end points.
// This function could also reside within wl_range class, but
// that would still require passing container in.
-template <class C>
-wl_range<C>
-wl_erase(C & c, typename C::iterator & w)
-{
- typename C::iterator it = c.erase(w);
- return wl_range< C >(it, c.end());
+template <class C> wl_range<C> wl_erase(C& c, typename C::iterator& w) {
+ typename C::iterator it = c.erase(w);
+ return wl_range<C>(it, c.end());
}
-#define container_iterate_const(type, container, i) \
- for \
- (wl_const_range< type > i(container); \
- i; \
- ++i) \
+#define container_iterate_const(type, container, i) for (wl_const_range<type> i(container); i; ++i)
-#define container_iterate(type, container, i) \
- for \
- (wl_range< type > i(container); \
- i; \
- ++i) \
+#define container_iterate(type, container, i) for (wl_range<type> i(container); i; ++i)
#endif
=== modified file 'src/cookie_priority_queue.h'
--- src/cookie_priority_queue.h 2012-06-06 14:51:03 +0000
+++ src/cookie_priority_queue.h 2013-05-18 05:56:27 +0000
@@ -27,31 +27,29 @@
#include <boost/noncopyable.hpp>
-template<typename _Type>
-struct default_cookie_accessor;
-
-template<typename _Type>
-struct cookie_priority_queue_base {
- typedef _Type type;
- typedef std::vector<type *> container;
- typedef typename container::size_type size_type;
-
- struct cookie : boost::noncopyable {
- cookie() : pos(bad_pos()) {}
- ~cookie() {}
-
- /** Returns \c true if the cookie is currently managed by a queue */
- bool is_active() const {return pos != bad_pos();}
-
- private:
- friend struct cookie_priority_queue_base<_Type>;
-
- size_type pos;
- };
-
-protected:
- static size_type & cookie_pos(cookie & cookie) {return cookie.pos;}
- static size_type bad_pos() {return std::numeric_limits<size_type>::max();}
+template <typename _Type> struct default_cookie_accessor;
+
+template <typename _Type> struct cookie_priority_queue_base {
+ typedef _Type type;
+ typedef std::vector<type*> container;
+ typedef typename container::size_type size_type;
+
+ struct cookie : boost::noncopyable {
+ cookie() : pos(bad_pos()) {}
+ ~cookie() {}
+
+ /** Returns \c true if the cookie is currently managed by a queue */
+ bool is_active() const { return pos != bad_pos(); }
+
+ private:
+ friend struct cookie_priority_queue_base<_Type>;
+
+ size_type pos;
+ };
+
+ protected:
+ static size_type& cookie_pos(cookie& cookie) { return cookie.pos; }
+ static size_type bad_pos() { return std::numeric_limits<size_type>::max(); }
};
/**
@@ -71,225 +69,215 @@
* you have to call \ref decrease_key or \ref increase_key after the change,
* depending on whether the change caused a decrease or increase, respectively.
*/
-template
- <typename _Type,
- typename _Compare = std::less<_Type>,
- typename _CookieAccessor = default_cookie_accessor<_Type> >
+template <typename _Type,
+ typename _Compare = std::less<_Type>,
+ typename _CookieAccessor = default_cookie_accessor<_Type> >
struct cookie_priority_queue : cookie_priority_queue_base<_Type> {
- typedef typename cookie_priority_queue_base<_Type>::type type;
- typedef typename cookie_priority_queue_base<_Type>::container container;
- typedef typename cookie_priority_queue_base<_Type>::size_type size_type;
- typedef typename cookie_priority_queue_base<_Type>::cookie cookie;
-
- typedef cookie_priority_queue_base<_Type> base_type;
- typedef _Compare compare;
- typedef _CookieAccessor cookie_accessor;
-
- cookie_priority_queue(const compare & _c = compare(), const cookie_accessor & _a = cookie_accessor());
- ~cookie_priority_queue();
-
- size_type size() const;
- bool empty() const;
- type * top() const;
-
- void push(type * elt);
- void pop(type * elt);
- void decrease_key(type * elt);
- void increase_key(type * elt);
-
-private:
- container d;
- compare c;
- cookie_accessor ca;
-
- void swap(cookie & a, cookie & b);
- void selftest();
-
- static size_type & cookie_pos(cookie & c) {return base_type::cookie_pos(c);}
- static size_type bad_pos() {return base_type::bad_pos();}
- static size_type parent_pos(size_type pos) {return (pos - 1) / 2;}
- static size_type left_child_pos(size_type pos) {return (2 * pos) + 1;}
- static size_type right_child_pos(size_type pos) {return (2 * pos) + 2;}
-};
-
-template<typename _Type>
-struct default_cookie_accessor {
- typedef typename cookie_priority_queue_base<_Type>::cookie cookie;
-
- cookie & operator()(_Type * t) {
- return t->cookie();
- }
-};
-
-
-template<typename _T, typename _Cw, typename _CA>
-cookie_priority_queue<_T, _Cw, _CA>::cookie_priority_queue
- (const typename cookie_priority_queue<_T, _Cw, _CA>::compare & _c,
- const typename cookie_priority_queue<_T, _Cw, _CA>::cookie_accessor & _a)
-: c(_c), ca(_a)
-{
-}
-
-template<typename _T, typename _Cw, typename _CA>
-cookie_priority_queue<_T, _Cw, _CA>::~cookie_priority_queue()
-{
- for (typename container::iterator it = d.begin(); it != d.end(); ++it)
- cookie_pos(ca(*it)) = bad_pos();
-}
-
-template<typename _T, typename _Cw, typename _CA>
-typename cookie_priority_queue<_T, _Cw, _CA>::size_type cookie_priority_queue<_T, _Cw, _CA>::size() const
-{
- return d.size();
-}
-
-template<typename _T, typename _Cw, typename _CA>
-bool cookie_priority_queue<_T, _Cw, _CA>::empty() const
-{
- return d.empty();
-}
-
-template<typename _T, typename _Cw, typename _CA>
-typename cookie_priority_queue<_T, _Cw, _CA>::type * cookie_priority_queue<_T, _Cw, _CA>::top() const
-{
- return *d.begin();
-}
-
-template<typename _T, typename _Cw, typename _CA>
-void cookie_priority_queue<_T, _Cw, _CA>::push
- (typename cookie_priority_queue<_T, _Cw, _CA>::type * elt)
-{
- cookie & elt_cookie(ca(elt));
-
- assert(cookie_pos(elt_cookie) == base_type::bad_pos());
-
- d.push_back(elt);
- cookie_pos(elt_cookie) = d.size() - 1;
-
- decrease_key(elt);
-}
-
-template<typename _T, typename _Cw, typename _CA>
-void cookie_priority_queue<_T, _Cw, _CA>::pop
- (typename cookie_priority_queue<_T, _Cw, _CA>::type * elt)
-{
- cookie & elt_cookie(ca(elt));
-
- assert(cookie_pos(elt_cookie) < d.size());
-
- while (cookie_pos(elt_cookie) > 0) {
- cookie & parent_cookie = ca(*(d.begin() + parent_pos(cookie_pos(elt_cookie))));
-
- assert(cookie_pos(parent_cookie) == parent_pos(cookie_pos(elt_cookie)));
-
- swap(elt_cookie, parent_cookie);
- }
-
- swap(elt_cookie, ca(d.back()));
- d.pop_back();
- cookie_pos(elt_cookie) = base_type::bad_pos();
-
- if (!d.empty())
- increase_key(*d.begin());
-}
-
-template<typename _T, typename _Cw, typename _CA>
-void cookie_priority_queue<_T, _Cw, _CA>::decrease_key
- (typename cookie_priority_queue<_T, _Cw, _CA>::type * elt)
-{
- cookie & elt_cookie(ca(elt));
-
- assert(cookie_pos(elt_cookie) < d.size());
-
- while (cookie_pos(elt_cookie) != 0) {
- size_type parent = parent_pos(cookie_pos(elt_cookie));
-
- if (!c(*elt, *d[parent]))
- break;
-
- cookie & parent_cookie(ca(d[parent]));
-
- assert(cookie_pos(parent_cookie) == parent);
-
- swap(elt_cookie, parent_cookie);
- }
-
- //selftest();
-}
-
-template<typename _T, typename _Cw, typename _CA>
-void cookie_priority_queue<_T, _Cw, _CA>::increase_key
- (typename cookie_priority_queue<_T, _Cw, _CA>::type * elt)
-{
- cookie & elt_cookie(ca(elt));
-
- assert(cookie_pos(elt_cookie) < d.size());
-
- for (;;) {
- size_type left_child = left_child_pos(cookie_pos(elt_cookie));
- size_type right_child = right_child_pos(cookie_pos(elt_cookie));
-
- if (left_child >= d.size())
- break;
-
- cookie & left_cookie(ca(d[left_child]));
-
- assert(cookie_pos(left_cookie) == left_child);
-
- if (c(**(d.begin() + left_child), *elt)) {
- if (right_child >= d.size() || c(*d[left_child], *d[right_child])) {
- swap(elt_cookie, left_cookie);
- continue;
- }
- }
-
- if (right_child >= d.size())
- break;
-
- cookie & right_cookie(ca(d[right_child]));
-
- assert(cookie_pos(right_cookie) == right_child);
-
- if (c(*d[right_child], *elt)) {
- swap(elt_cookie, right_cookie);
- continue;
- }
-
- break;
- }
-
- //selftest();
-}
-
-template<typename _T, typename _Cw, typename _CA>
-void cookie_priority_queue<_T, _Cw, _CA>::swap
- (typename cookie_priority_queue<_T, _Cw, _CA>::cookie & a,
- typename cookie_priority_queue<_T, _Cw, _CA>::cookie & b)
-{
- std::swap(d[cookie_pos(a)], d[cookie_pos(b)]);
- std::swap(cookie_pos(a), cookie_pos(b));
+ typedef typename cookie_priority_queue_base<_Type>::type type;
+ typedef typename cookie_priority_queue_base<_Type>::container container;
+ typedef typename cookie_priority_queue_base<_Type>::size_type size_type;
+ typedef typename cookie_priority_queue_base<_Type>::cookie cookie;
+
+ typedef cookie_priority_queue_base<_Type> base_type;
+ typedef _Compare compare;
+ typedef _CookieAccessor cookie_accessor;
+
+ cookie_priority_queue(const compare& _c = compare(),
+ const cookie_accessor& _a = cookie_accessor());
+ ~cookie_priority_queue();
+
+ size_type size() const;
+ bool empty() const;
+ type* top() const;
+
+ void push(type* elt);
+ void pop(type* elt);
+ void decrease_key(type* elt);
+ void increase_key(type* elt);
+
+ private:
+ container d;
+ compare c;
+ cookie_accessor ca;
+
+ void swap(cookie& a, cookie& b);
+ void selftest();
+
+ static size_type& cookie_pos(cookie& c) { return base_type::cookie_pos(c); }
+ static size_type bad_pos() { return base_type::bad_pos(); }
+ static size_type parent_pos(size_type pos) { return (pos - 1) / 2; }
+ static size_type left_child_pos(size_type pos) { return (2 * pos) + 1; }
+ static size_type right_child_pos(size_type pos) { return (2 * pos) + 2; }
+};
+
+template <typename _Type> struct default_cookie_accessor {
+ typedef typename cookie_priority_queue_base<_Type>::cookie cookie;
+
+ cookie& operator()(_Type* t) { return t->cookie(); }
+};
+
+template <typename _T, typename _Cw, typename _CA>
+cookie_priority_queue<_T, _Cw, _CA>::cookie_priority_queue(
+ const typename cookie_priority_queue<_T, _Cw, _CA>::compare& _c,
+ const typename cookie_priority_queue<_T, _Cw, _CA>::cookie_accessor& _a)
+ : c(_c), ca(_a) {}
+
+template <typename _T, typename _Cw, typename _CA>
+cookie_priority_queue<_T, _Cw, _CA>::~cookie_priority_queue() {
+ for (typename container::iterator it = d.begin(); it != d.end(); ++it)
+ cookie_pos(ca(*it)) = bad_pos();
+}
+
+template <typename _T, typename _Cw, typename _CA>
+typename cookie_priority_queue<_T, _Cw, _CA>::size_type
+cookie_priority_queue<_T, _Cw, _CA>::size() const {
+ return d.size();
+}
+
+template <typename _T, typename _Cw, typename _CA>
+bool
+cookie_priority_queue<_T, _Cw, _CA>::empty() const {
+ return d.empty();
+}
+
+template <typename _T, typename _Cw, typename _CA>
+typename cookie_priority_queue<_T, _Cw, _CA>::type*
+cookie_priority_queue<_T, _Cw, _CA>::top() const {
+ return *d.begin();
+}
+
+template <typename _T, typename _Cw, typename _CA>
+void
+cookie_priority_queue<_T, _Cw, _CA>::push(typename cookie_priority_queue<_T, _Cw, _CA>::type* elt) {
+ cookie& elt_cookie(ca(elt));
+
+ assert(cookie_pos(elt_cookie) == base_type::bad_pos());
+
+ d.push_back(elt);
+ cookie_pos(elt_cookie) = d.size() - 1;
+
+ decrease_key(elt);
+}
+
+template <typename _T, typename _Cw, typename _CA>
+void
+cookie_priority_queue<_T, _Cw, _CA>::pop(typename cookie_priority_queue<_T, _Cw, _CA>::type* elt) {
+ cookie& elt_cookie(ca(elt));
+
+ assert(cookie_pos(elt_cookie) < d.size());
+
+ while (cookie_pos(elt_cookie) > 0) {
+ cookie& parent_cookie = ca(*(d.begin() + parent_pos(cookie_pos(elt_cookie))));
+
+ assert(cookie_pos(parent_cookie) == parent_pos(cookie_pos(elt_cookie)));
+
+ swap(elt_cookie, parent_cookie);
+ }
+
+ swap(elt_cookie, ca(d.back()));
+ d.pop_back();
+ cookie_pos(elt_cookie) = base_type::bad_pos();
+
+ if (!d.empty())
+ increase_key(*d.begin());
+}
+
+template <typename _T, typename _Cw, typename _CA>
+void
+cookie_priority_queue<_T, _Cw, _CA>::decrease_key(
+ typename cookie_priority_queue<_T, _Cw, _CA>::type* elt) {
+ cookie& elt_cookie(ca(elt));
+
+ assert(cookie_pos(elt_cookie) < d.size());
+
+ while (cookie_pos(elt_cookie) != 0) {
+ size_type parent = parent_pos(cookie_pos(elt_cookie));
+
+ if (!c(*elt, *d[parent]))
+ break;
+
+ cookie& parent_cookie(ca(d[parent]));
+
+ assert(cookie_pos(parent_cookie) == parent);
+
+ swap(elt_cookie, parent_cookie);
+ }
+
+ //selftest();
+}
+
+template <typename _T, typename _Cw, typename _CA>
+void
+cookie_priority_queue<_T, _Cw, _CA>::increase_key(
+ typename cookie_priority_queue<_T, _Cw, _CA>::type* elt) {
+ cookie& elt_cookie(ca(elt));
+
+ assert(cookie_pos(elt_cookie) < d.size());
+
+ for (;;) {
+ size_type left_child = left_child_pos(cookie_pos(elt_cookie));
+ size_type right_child = right_child_pos(cookie_pos(elt_cookie));
+
+ if (left_child >= d.size())
+ break;
+
+ cookie& left_cookie(ca(d[left_child]));
+
+ assert(cookie_pos(left_cookie) == left_child);
+
+ if (c(**(d.begin() + left_child), *elt)) {
+ if (right_child >= d.size() || c(*d[left_child], *d[right_child])) {
+ swap(elt_cookie, left_cookie);
+ continue;
+ }
+ }
+
+ if (right_child >= d.size())
+ break;
+
+ cookie& right_cookie(ca(d[right_child]));
+
+ assert(cookie_pos(right_cookie) == right_child);
+
+ if (c(*d[right_child], *elt)) {
+ swap(elt_cookie, right_cookie);
+ continue;
+ }
+
+ break;
+ }
+
+ //selftest();
+}
+
+template <typename _T, typename _Cw, typename _CA>
+void
+cookie_priority_queue<_T, _Cw, _CA>::swap(typename cookie_priority_queue<_T, _Cw, _CA>::cookie& a,
+ typename cookie_priority_queue<_T, _Cw, _CA>::cookie& b) {
+ std::swap(d[cookie_pos(a)], d[cookie_pos(b)]);
+ std::swap(cookie_pos(a), cookie_pos(b));
}
// Disable in release builds.
-template<typename _T, typename _Cw, typename _CA>
-void cookie_priority_queue<_T, _Cw, _CA>::selftest()
-{
- for (size_type pos = 0; pos < d.size(); ++pos) {
- cookie & elt_cookie(ca(d[pos]));
-
- assert(cookie_pos(elt_cookie) == pos);
-
- size_type left_child = left_child_pos(pos);
- size_type right_child = right_child_pos(pos);
-
- if (left_child < d.size()) {
- assert(!c(*d[left_child], *d[pos]));
- }
-
- if (right_child < d.size()) {
- assert(!c(*d[right_child], *d[pos]));
- }
- }
+template <typename _T, typename _Cw, typename _CA>
+void
+cookie_priority_queue<_T, _Cw, _CA>::selftest() {
+ for (size_type pos = 0; pos < d.size(); ++pos) {
+ cookie& elt_cookie(ca(d[pos]));
+
+ assert(cookie_pos(elt_cookie) == pos);
+
+ size_type left_child = left_child_pos(pos);
+ size_type right_child = right_child_pos(pos);
+
+ if (left_child < d.size()) {
+ assert(!c(*d[left_child], *d[pos]));
+ }
+
+ if (right_child < d.size()) {
+ assert(!c(*d[right_child], *d[pos]));
+ }
+ }
}
-#endif // COOKIE_PRIORITY_QUEUE_H
+#endif // COOKIE_PRIORITY_QUEUE_H
=== modified file 'src/debugconsole.cc'
--- src/debugconsole.cc 2013-02-10 19:36:24 +0000
+++ src/debugconsole.cc 2013-05-18 05:56:27 +0000
@@ -28,121 +28,95 @@
namespace DebugConsole {
struct Console : public ChatProvider, public Handler {
- typedef std::map<std::string, Handler::HandlerFn> CommandMap;
-
- std::vector<ChatMessage> messages;
- CommandMap commands;
- Handler::HandlerFn default_handler;
-
- Console()
- {
- addCommand("help", boost::bind(&Console::cmdHelp, this, _1));
- addCommand("ls", boost::bind(&Console::cmdLs, this, _1));
- default_handler = boost::bind(&Console::cmdErr, this, _1);
- }
-
- ~Console()
- {
- }
-
- void cmdHelp(const std::vector<std::string> &)
- {
- write("Use 'ls' to list all available commands.");
- }
-
- void cmdLs(const std::vector<std::string> &)
- {
- container_iterate_const(CommandMap, commands, i)
- write(i.current->first);
- }
-
- void cmdErr(const std::vector<std::string> & args) {
- write("Unknown command: " + args[0]);
- }
-
- void send(const std::string & msg)
- {
- std::vector<std::string> arg;
- std::string::size_type pos = 0;
-
- write("# " + msg);
-
- while ((pos = msg.find_first_not_of(' ', pos)) != std::string::npos) {
- std::string::size_type const end = msg.find(' ', pos);
- arg.push_back(msg.substr(pos, end - pos));
- pos = end;
- }
-
- if (arg.empty())
- return;
-
- CommandMap::const_iterator it = commands.find(arg[0]);
- if (it == commands.end()) {
- default_handler(arg);
- return;
- }
-
- it->second(arg);
- }
-
- const std::vector<ChatMessage> & getMessages() const
- {
- return messages;
- }
-
- void write(const std::string & msg)
- {
- ChatMessage cm;
-
- cm.time = time(0);
- cm.msg = msg;
- messages.push_back(cm);
-
- log("*** %s\n", msg.c_str());
-
- // Arbitrary choice of backlog size
- if (messages.size() > 1000)
- messages.erase(messages.begin(), messages.begin() + 100);
-
- ChatProvider::send(cm); // Notify listeners, i.e. the UI
- }
+ typedef std::map<std::string, Handler::HandlerFn> CommandMap;
+
+ std::vector<ChatMessage> messages;
+ CommandMap commands;
+ Handler::HandlerFn default_handler;
+
+ Console() {
+ addCommand("help", boost::bind(&Console::cmdHelp, this, _1));
+ addCommand("ls", boost::bind(&Console::cmdLs, this, _1));
+ default_handler = boost::bind(&Console::cmdErr, this, _1);
+ }
+
+ ~Console() {}
+
+ void cmdHelp(const std::vector<std::string>&) {
+ write("Use 'ls' to list all available commands.");
+ }
+
+ void cmdLs(const std::vector<std::string>&) {
+ container_iterate_const(CommandMap, commands, i)
+ write(i.current->first);
+ }
+
+ void cmdErr(const std::vector<std::string>& args) { write("Unknown command: " + args[0]); }
+
+ void send(const std::string& msg) {
+ std::vector<std::string> arg;
+ std::string::size_type pos = 0;
+
+ write("# " + msg);
+
+ while ((pos = msg.find_first_not_of(' ', pos)) != std::string::npos) {
+ std::string::size_type const end = msg.find(' ', pos);
+ arg.push_back(msg.substr(pos, end - pos));
+ pos = end;
+ }
+
+ if (arg.empty())
+ return;
+
+ CommandMap::const_iterator it = commands.find(arg[0]);
+ if (it == commands.end()) {
+ default_handler(arg);
+ return;
+ }
+
+ it->second(arg);
+ }
+
+ const std::vector<ChatMessage>& getMessages() const { return messages; }
+
+ void write(const std::string& msg) {
+ ChatMessage cm;
+
+ cm.time = time(0);
+ cm.msg = msg;
+ messages.push_back(cm);
+
+ log("*** %s\n", msg.c_str());
+
+ // Arbitrary choice of backlog size
+ if (messages.size() > 1000)
+ messages.erase(messages.begin(), messages.begin() + 100);
+
+ ChatProvider::send(cm); // Notify listeners, i.e. the UI
+ }
};
Console g_console;
-ChatProvider * getChatProvider()
-{
- return &g_console;
-}
-
-void write(const std::string & text)
-{
- g_console.write(text);
-}
-
-
-Handler::Handler()
-{
-}
-
-Handler::~Handler()
-{
- // This check is an evil hack to account for the singleton-nature
- // of the Console
- if (this != &g_console)
- container_iterate_const(std::vector<std::string>, m_commands, i)
- g_console.commands.erase(*i.current);
-}
-
-void Handler::addCommand(const std::string & cmd, const HandlerFn & fun)
-{
- g_console.commands[cmd] = fun;
- m_commands.push_back(cmd);
-}
-
-void Handler::setDefaultCommand(const HandlerFn & fun)
-{
- g_console.default_handler = fun;
-}
+ChatProvider* getChatProvider() { return &g_console; }
+
+void write(const std::string& text) { g_console.write(text); }
+
+Handler::Handler() {}
+
+Handler::~Handler() {
+ // This check is an evil hack to account for the singleton-nature
+ // of the Console
+ if (this != &g_console)
+ container_iterate_const(std::vector<std::string>, m_commands, i)
+ g_console.commands.erase(*i.current);
+}
+
+void Handler::addCommand(const std::string& cmd, const HandlerFn& fun) {
+ g_console.commands[cmd] = fun;
+ m_commands.push_back(cmd);
+}
+
+void Handler::setDefaultCommand(const HandlerFn& fun) { g_console.default_handler = fun; }
}
=== modified file 'src/debugconsole.h'
--- src/debugconsole.h 2013-02-10 19:36:24 +0000
+++ src/debugconsole.h 2013-05-18 05:56:27 +0000
@@ -45,22 +45,22 @@
* runs.
*/
struct Handler {
- /**
- * Type for command callback functions.
- * The passed array contains a list of all (space-separated) components
- * of the command, including the command name itself.
- */
- typedef boost::function<void (const std::vector<std::string> &)> HandlerFn;
-
- Handler();
- virtual ~Handler();
-
-protected:
- void addCommand(const std::string &, const HandlerFn &);
- void setDefaultCommand(const HandlerFn &);
-
-private:
- std::vector<std::string> m_commands;
+ /**
+ * Type for command callback functions.
+ * The passed array contains a list of all (space-separated) components
+ * of the command, including the command name itself.
+ */
+ typedef boost::function<void(const std::vector<std::string>&)> HandlerFn;
+
+ Handler();
+ virtual ~Handler();
+
+ protected:
+ void addCommand(const std::string&, const HandlerFn&);
+ void setDefaultCommand(const HandlerFn&);
+
+ private:
+ std::vector<std::string> m_commands;
};
/**
@@ -69,7 +69,7 @@
* the given command string, and the log of messages contains a log
* of console messages.
*/
-ChatProvider * getChatProvider();
+ChatProvider* getChatProvider();
/**
* Write some output on the console.
@@ -81,7 +81,7 @@
* \ref getChatProvider(). Sending a message via \ref getChatProvider()
* executes a command, while this function writes to the console.
*/
-void write(const std::string & text);
+void write(const std::string& text);
}
=== modified file 'src/descr_maintainer.h'
--- src/descr_maintainer.h 2013-02-10 19:36:24 +0000
+++ src/descr_maintainer.h 2013-05-18 05:56:27 +0000
@@ -28,111 +28,92 @@
* Worker_Descr and so on.
*/
template <typename T> struct Descr_Maintainer {
- Descr_Maintainer() : capacity(0), nitemsw(0), items(0) {}
- ~Descr_Maintainer();
-
- static typename T::Index invalid_index() {
- return std::numeric_limits<typename T::Index>::max();
- }
-
- T * exists(char const * name) const;
- int32_t add(T *);
- typename T::Index get_nitems() const throw () {return nitemsw;}
-
- struct Nonexistent {};
-
- int32_t get_index(const std::string & name) const throw (Nonexistent)
- {
- for (typename T::Index i = 0; i < nitemsw; ++i)
- if (name == items[i]->name())
- return i;
- return -1;
- }
-
- int32_t get_index(const char * const name) const throw (Nonexistent)
- {
- for (typename T::Index i = 0; i < nitemsw; ++i)
- if (name == items[i]->name())
- return i;
- return -1;
- }
-
- T * get(int32_t const idx) const {
- return idx >= 0 and idx < static_cast<int32_t>(nitemsw) ? items[idx] : 0;
- }
-
-private:
- typename T::Index capacity;
- typename T::Index nitemsw;
- T * * items;
-
- void reserve(const typename T::Index n) {
- T * * const new_items =
- static_cast<T * *>(realloc(items, sizeof(T *) * n));
- if (not new_items)
- throw std::bad_alloc();
- items = new_items;
- capacity = n;
- }
+ Descr_Maintainer() : capacity(0), nitemsw(0), items(0) {}
+ ~Descr_Maintainer();
+
+ static typename T::Index invalid_index() {
+ return std::numeric_limits<typename T::Index>::max();
+ }
+
+ T* exists(char const* name) const;
+ int32_t add(T*);
+ typename T::Index get_nitems() const throw() { return nitemsw; }
+
+ struct Nonexistent {
+ };
+
+ int32_t get_index(const std::string& name) const throw(Nonexistent) {
+ for (typename T::Index i = 0; i < nitemsw; ++i)
+ if (name == items[i]->name())
+ return i;
+ return -1;
+ }
+
+ int32_t get_index(const char* const name) const throw(Nonexistent) {
+ for (typename T::Index i = 0; i < nitemsw; ++i)
+ if (name == items[i]->name())
+ return i;
+ return -1;
+ }
+
+ T* get(int32_t const idx) const {
+ return idx >= 0 and idx < static_cast<int32_t>(nitemsw) ? items[idx] : 0;
+ }
+
+ private:
+ typename T::Index capacity;
+ typename T::Index nitemsw;
+ T** items;
+
+ void reserve(const typename T::Index n) {
+ T** const new_items = static_cast<T**>(realloc(items, sizeof(T*) * n));
+ if (not new_items)
+ throw std::bad_alloc();
+ items = new_items;
+ capacity = n;
+ }
};
-
-template <typename T>
-int32_t Descr_Maintainer<T>::add(T * const item) {
- int32_t const result = nitemsw;
- if (++nitemsw >= capacity)
- reserve(nitemsw);
- items[result] = item;
- return result;
+template <typename T> int32_t Descr_Maintainer<T>::add(T* const item) {
+ int32_t const result = nitemsw;
+ if (++nitemsw >= capacity)
+ reserve(nitemsw);
+ items[result] = item;
+ return result;
}
/// Returns the element if it exists, 0 otherwise.
-template <typename T>
-T * Descr_Maintainer<T>::exists(char const * const name) const {
- for (typename T::Index i = 0; i < nitemsw; ++i)
- if (name == items[i]->name())
- return items[i];
- return 0;
+template <typename T> T* Descr_Maintainer<T>::exists(char const* const name) const {
+ for (typename T::Index i = 0; i < nitemsw; ++i)
+ if (name == items[i]->name())
+ return items[i];
+ return 0;
}
-template<typename T> Descr_Maintainer<T>::~Descr_Maintainer() {
- for (typename T::Index i = 0; i < nitemsw; ++i)
- delete items[i];
- free(items);
+template <typename T> Descr_Maintainer<T>::~Descr_Maintainer() {
+ for (typename T::Index i = 0; i < nitemsw; ++i)
+ delete items[i];
+ free(items);
}
/// This template is used to have a typesafe maintainer for Bob_Descr,
/// Worker_Descr and so on. This version uses boxed Index type for indexing.
/// Usage: Indexed_Descr_Maintainer<Worker_Descr, Ware_Index> workers;
-template <typename T, typename T_Index> struct Indexed_Descr_Maintainer :
-private Descr_Maintainer<T>
-{
- T * exists(char const * const name) {
- return Descr_Maintainer<T>::exists(name);
- }
- T_Index add(T * const t) {
- return
- T_Index
- (static_cast<typename T_Index::value_t>
- (Descr_Maintainer<T>::add(t)));
- }
- T_Index get_nitems() const throw () {
- return T_Index(Descr_Maintainer<T>::get_nitems());
- }
- T_Index get_index(const std::string & name) const throw () {
- int32_t idx = Descr_Maintainer<T>::get_index(name);
- return
- idx == -1 ? T_Index::Null() :
- T_Index(static_cast<typename T_Index::value_t>(idx));
- }
- T_Index get_index(const char * const name) const throw () {
- int32_t idx = Descr_Maintainer<T>::get_index(name);
- return
- idx == -1 ? T_Index::Null() :
- T_Index(static_cast<typename T_Index::value_t>(idx));
- }
- T * get(T_Index const idx) const {
- return idx ? Descr_Maintainer<T>::get(idx.value()) : 0;
- }
+template <typename T, typename T_Index>
+struct Indexed_Descr_Maintainer : private Descr_Maintainer<T> {
+ T* exists(char const* const name) { return Descr_Maintainer<T>::exists(name); }
+ T_Index add(T* const t) {
+ return T_Index(static_cast<typename T_Index::value_t>(Descr_Maintainer<T>::add(t)));
+ }
+ T_Index get_nitems() const throw() { return T_Index(Descr_Maintainer<T>::get_nitems()); }
+ T_Index get_index(const std::string& name) const throw() {
+ int32_t idx = Descr_Maintainer<T>::get_index(name);
+ return idx == -1 ? T_Index::Null() : T_Index(static_cast<typename T_Index::value_t>(idx));
+ }
+ T_Index get_index(const char* const name) const throw() {
+ int32_t idx = Descr_Maintainer<T>::get_index(name);
+ return idx == -1 ? T_Index::Null() : T_Index(static_cast<typename T_Index::value_t>(idx));
+ }
+ T* get(T_Index const idx) const { return idx ? Descr_Maintainer<T>::get(idx.value()) : 0; }
};
#endif
=== modified file 'src/economy/cmd_call_economy_balance.cc'
--- src/economy/cmd_call_economy_balance.cc 2013-02-10 19:36:24 +0000
+++ src/economy/cmd_call_economy_balance.cc 2013-05-18 05:56:27 +0000
@@ -28,22 +28,21 @@
namespace Widelands {
-Cmd_Call_Economy_Balance::Cmd_Call_Economy_Balance
- (int32_t const starttime, Economy * const economy, uint32_t const timerid)
- : GameLogicCommand(starttime)
-{
- m_flag = &economy->get_arbitrary_flag();
- m_timerid = timerid;
+Cmd_Call_Economy_Balance::Cmd_Call_Economy_Balance(int32_t const starttime,
+ Economy* const economy,
+ uint32_t const timerid)
+ : GameLogicCommand(starttime) {
+ m_flag = &economy->get_arbitrary_flag();
+ m_timerid = timerid;
}
/**
* Called by Cmd_Queue as requested by start_request_timer().
* Call economy functions to balance supply and request.
*/
-void Cmd_Call_Economy_Balance::execute(Game & game)
-{
- if (Flag * const flag = m_flag.get(game))
- flag->get_economy()->balance(m_timerid);
+void Cmd_Call_Economy_Balance::execute(Game& game) {
+ if (Flag* const flag = m_flag.get(game))
+ flag->get_economy()->balance(m_timerid);
}
#define CURRENT_CMD_CALL_ECONOMY_VERSION 3
@@ -51,55 +50,53 @@
/**
* Read and write
*/
-void Cmd_Call_Economy_Balance::Read
- (FileRead & fr, Editor_Game_Base & egbase, Map_Map_Object_Loader & mol)
-{
- try {
- uint16_t const packet_version = fr.Unsigned16();
- if (packet_version == CURRENT_CMD_CALL_ECONOMY_VERSION) {
- GameLogicCommand::Read(fr, egbase, mol);
- uint32_t serial = fr.Unsigned32();
- if (serial)
- m_flag = &mol.get<Flag>(serial);
- m_timerid = fr.Unsigned32();
- } else if (packet_version == 1 || packet_version == 2) {
- GameLogicCommand::Read(fr, egbase, mol);
- uint8_t const player_number = fr.Unsigned8();
- if (Player * const player = egbase.get_player(player_number)) {
- if (not fr.Unsigned8())
- throw wexception("0 is not allowed here");
- uint16_t const economy_number = fr.Unsigned16();
- if (economy_number < player->get_nr_economies())
- m_flag =
- &player->get_economy_by_number(economy_number)
- ->get_arbitrary_flag();
- else
- throw wexception("invalid economy number %u", economy_number);
- } else
- throw wexception("invalid player number %u", player_number);
- if (packet_version >= 2)
- m_timerid = fr.Unsigned32();
- else
- m_timerid = 0;
- } else
- throw game_data_error
- (_("unknown/unhandled version %u"), packet_version);
- } catch (const _wexception & e) {
- throw wexception(_("call economy balance: %s"), e.what());
- }
+void Cmd_Call_Economy_Balance::Read(FileRead& fr,
+ Editor_Game_Base& egbase,
+ Map_Map_Object_Loader& mol) {
+ try {
+ uint16_t const packet_version = fr.Unsigned16();
+ if (packet_version == CURRENT_CMD_CALL_ECONOMY_VERSION) {
+ GameLogicCommand::Read(fr, egbase, mol);
+ uint32_t serial = fr.Unsigned32();
+ if (serial)
+ m_flag = &mol.get<Flag>(serial);
+ m_timerid = fr.Unsigned32();
+ } else if (packet_version == 1 || packet_version == 2) {
+ GameLogicCommand::Read(fr, egbase, mol);
+ uint8_t const player_number = fr.Unsigned8();
+ if (Player* const player = egbase.get_player(player_number)) {
+ if (not fr.Unsigned8())
+ throw wexception("0 is not allowed here");
+ uint16_t const economy_number = fr.Unsigned16();
+ if (economy_number < player->get_nr_economies())
+ m_flag = &player->get_economy_by_number(economy_number)->get_arbitrary_flag();
+ else
+ throw wexception("invalid economy number %u", economy_number);
+ } else
+ throw wexception("invalid player number %u", player_number);
+ if (packet_version >= 2)
+ m_timerid = fr.Unsigned32();
+ else
+ m_timerid = 0;
+ } else
+ throw game_data_error(_("unknown/unhandled version %u"), packet_version);
+ }
+ catch (const _wexception & e) {
+ throw wexception(_("call economy balance: %s"), e.what());
+ }
}
-void Cmd_Call_Economy_Balance::Write
- (FileWrite & fw, Editor_Game_Base & egbase, Map_Map_Object_Saver & mos)
-{
- fw.Unsigned16(CURRENT_CMD_CALL_ECONOMY_VERSION);
+void Cmd_Call_Economy_Balance::Write(FileWrite& fw,
+ Editor_Game_Base& egbase,
+ Map_Map_Object_Saver& mos) {
+ fw.Unsigned16(CURRENT_CMD_CALL_ECONOMY_VERSION);
- // Write Base Commands
- GameLogicCommand::Write(fw, egbase, mos);
- if (Flag * const flag = m_flag.get(egbase))
- fw.Unsigned32(mos.get_object_file_index(*flag));
- else
- fw.Unsigned32(0);
- fw.Unsigned32(m_timerid);
+ // Write Base Commands
+ GameLogicCommand::Write(fw, egbase, mos);
+ if (Flag* const flag = m_flag.get(egbase))
+ fw.Unsigned32(mos.get_object_file_index(*flag));
+ else
+ fw.Unsigned32(0);
+ fw.Unsigned32(m_timerid);
}
}
=== modified file 'src/economy/cmd_call_economy_balance.h'
--- src/economy/cmd_call_economy_balance.h 2013-04-22 20:15:00 +0000
+++ src/economy/cmd_call_economy_balance.h 2013-05-18 05:56:27 +0000
@@ -30,26 +30,23 @@
struct Map_Map_Object_Loader;
struct Map_Map_Object_Loader;
-
struct Cmd_Call_Economy_Balance : public GameLogicCommand {
- Cmd_Call_Economy_Balance () : GameLogicCommand(0), m_timerid(0) {} ///< for load and save
-
- Cmd_Call_Economy_Balance (int32_t starttime, Economy *, uint32_t timerid);
-
- void execute (Game &);
-
- virtual uint8_t id() const {return QUEUE_CMD_CALL_ECONOMY_BALANCE;}
-
- void Write(FileWrite &, Editor_Game_Base &, Map_Map_Object_Saver &);
- void Read (FileRead &, Editor_Game_Base &, Map_Map_Object_Loader &);
-
-private:
- OPtr<Flag> m_flag;
- uint32_t m_timerid;
+ Cmd_Call_Economy_Balance() : GameLogicCommand(0), m_timerid(0) {} ///< for load and save
+
+ Cmd_Call_Economy_Balance(int32_t starttime, Economy*, uint32_t timerid);
+
+ void execute(Game&);
+
+ virtual uint8_t id() const { return QUEUE_CMD_CALL_ECONOMY_BALANCE; }
+
+ void Write(FileWrite&, Editor_Game_Base&, Map_Map_Object_Saver&);
+ void Read(FileRead&, Editor_Game_Base&, Map_Map_Object_Loader&);
+
+ private:
+ OPtr<Flag> m_flag;
+ uint32_t m_timerid;
};
}
#endif
-
-
=== modified file 'src/economy/economy.cc'
--- src/economy/economy.cc 2013-04-22 20:15:00 +0000
+++ src/economy/economy.cc 2013-05-18 05:56:27 +0000
@@ -39,64 +39,55 @@
namespace Widelands {
-Economy::Economy(Player & player) :
- m_owner(player),
- m_request_timerid(0)
-{
- const Tribe_Descr & tribe = player.tribe();
- Ware_Index const nr_wares = tribe.get_nrwares();
- Ware_Index const nr_workers = tribe.get_nrworkers();
- m_wares.set_nrwares(nr_wares);
- m_workers.set_nrwares(nr_workers);
-
- player.add_economy(*this);
-
- m_ware_target_quantities = new Target_Quantity[nr_wares .value()];
- for (Ware_Index i = Ware_Index::First(); i < nr_wares; ++i) {
- Target_Quantity tq;
- tq.permanent =
- tribe.get_ware_descr(i)->default_target_quantity();
- tq.last_modified = 0;
- m_ware_target_quantities[i.value()] = tq;
- }
- m_worker_target_quantities = new Target_Quantity[nr_workers.value()];
- for (Ware_Index i = Ware_Index::First(); i < nr_workers; ++i) {
- Target_Quantity tq;
- tq.permanent =
- tribe.get_worker_descr(i)->default_target_quantity();
- tq.last_modified = 0;
- m_worker_target_quantities[i.value()] = tq;
- }
-
- m_router =
- new Router(boost::bind(&Economy::_reset_all_pathfinding_cycles, this));
-}
-
-Economy::~Economy()
-{
- m_owner.remove_economy(*this);
-
- if (m_requests.size())
- log("Warning: Economy still has requests left on destruction\n");
- if (m_flags.size())
- log("Warning: Economy still has flags left on destruction\n");
- if (m_warehouses.size())
- log("Warning: Economy still has warehouses left on destruction\n");
-
- delete[] m_ware_target_quantities;
- delete[] m_worker_target_quantities;
-
- delete m_router;
-}
-
+Economy::Economy(Player& player) : m_owner(player), m_request_timerid(0) {
+ const Tribe_Descr& tribe = player.tribe();
+ Ware_Index const nr_wares = tribe.get_nrwares();
+ Ware_Index const nr_workers = tribe.get_nrworkers();
+ m_wares.set_nrwares(nr_wares);
+ m_workers.set_nrwares(nr_workers);
+
+ player.add_economy(*this);
+
+ m_ware_target_quantities = new Target_Quantity[nr_wares.value()];
+ for (Ware_Index i = Ware_Index::First(); i < nr_wares; ++i) {
+ Target_Quantity tq;
+ tq.permanent = tribe.get_ware_descr(i)->default_target_quantity();
+ tq.last_modified = 0;
+ m_ware_target_quantities[i.value()] = tq;
+ }
+ m_worker_target_quantities = new Target_Quantity[nr_workers.value()];
+ for (Ware_Index i = Ware_Index::First(); i < nr_workers; ++i) {
+ Target_Quantity tq;
+ tq.permanent = tribe.get_worker_descr(i)->default_target_quantity();
+ tq.last_modified = 0;
+ m_worker_target_quantities[i.value()] = tq;
+ }
+
+ m_router = new Router(boost::bind(&Economy::_reset_all_pathfinding_cycles, this));
+}
+
+Economy::~Economy() {
+ m_owner.remove_economy(*this);
+
+ if (m_requests.size())
+ log("Warning: Economy still has requests left on destruction\n");
+ if (m_flags.size())
+ log("Warning: Economy still has flags left on destruction\n");
+ if (m_warehouses.size())
+ log("Warning: Economy still has warehouses left on destruction\n");
+
+ delete[] m_ware_target_quantities;
+ delete[] m_worker_target_quantities;
+
+ delete m_router;
+}
/**
* \return an arbitrary flag in this economy, or 0 if no flag exists
*/
-Flag & Economy::get_arbitrary_flag()
-{
- assert(m_flags.size());
- return *m_flags[0];
+Flag& Economy::get_arbitrary_flag() {
+ assert(m_flags.size());
+ return *m_flags[0];
}
/**
@@ -105,90 +96,86 @@
* Since we could merge into both directions, we preserve the economy that is
* currently bigger (should be more efficient).
*/
-void Economy::check_merge(Flag & f1, Flag & f2)
-{
- Economy * e1 = f1.get_economy();
- Economy * e2 = f2.get_economy();
- if (e1 != e2) {
- if (e1->get_nrflags() < e2->get_nrflags())
- std::swap(e1, e2);
- e1->_merge(*e2);
- }
+void Economy::check_merge(Flag& f1, Flag& f2) {
+ Economy* e1 = f1.get_economy();
+ Economy* e2 = f2.get_economy();
+ if (e1 != e2) {
+ if (e1->get_nrflags() < e2->get_nrflags())
+ std::swap(e1, e2);
+ e1->_merge(*e2);
+ }
}
/**
* Notify the economy that there may no longer be a connection between
* the given flags in the road and seafaring network.
*/
-void Economy::check_split(Flag & f1, Flag & f2)
-{
- assert(&f1 != &f2);
- assert(f1.get_economy() == f2.get_economy());
-
- Economy * e = f1.get_economy();
- // No economy in the editor.
- if (not e)
- return;
-
- e->m_split_checks.push_back(std::make_pair(OPtr<Flag>(&f1), OPtr<Flag>(&f2)));
- e->rebalance_supply(); // the real split-checking is done during rebalance
-}
-
-void Economy::_check_splits()
-{
- Editor_Game_Base & egbase = owner().egbase();
- Map & map = egbase.map();
-
- while (m_split_checks.size()) {
- Flag * f1 = m_split_checks.back().first.get(egbase);
- Flag * f2 = m_split_checks.back().second.get(egbase);
- m_split_checks.pop_back();
-
- if (!f1 || !f2) {
- if (!f1 && !f2)
- continue;
- if (!f1)
- f1 = f2;
- if (f1->get_economy() != this)
- continue;
-
- // Handle the case when two or more roads are removed simultaneously
- RouteAStar<AStarZeroEstimator> astar(*m_router, wwWORKER, AStarZeroEstimator());
- astar.push(*f1);
- std::set<OPtr<Flag> > reachable;
- while (RoutingNode * current = astar.step())
- reachable.insert(¤t->base_flag());
- if (reachable.size() != m_flags.size())
- _split(reachable);
- continue;
- }
-
- // If one (or both) of the flags have already been split off, we do not need to re-check
- if (f1->get_economy() != this || f2->get_economy() != this)
- continue;
-
- // Start an A-star searches from f1 with a heuristic bias towards f2,
- // because we do not need to do anything if f1 is still connected to f2.
- // If f2 is not reached by the search, split off all the nodes that have been
- // reached from f1. These nodes induce a connected subgraph.
- // This means that the newly created economy, which contains all the
- // flags that have been split, is already connected.
- RouteAStar<AStarEstimator> astar(*m_router, wwWORKER, AStarEstimator(map, *f2));
- astar.push(*f1);
- std::set<OPtr<Flag> > reachable;
-
- for (;;) {
- RoutingNode * current = astar.step();
- if (!current) {
- _split(reachable);
- break;
- } else if (current == f2)
- break;
- reachable.insert(¤t->base_flag());
- }
- }
-}
-
+void Economy::check_split(Flag& f1, Flag& f2) {
+ assert(&f1 != &f2);
+ assert(f1.get_economy() == f2.get_economy());
+
+ Economy* e = f1.get_economy();
+ // No economy in the editor.
+ if (not e)
+ return;
+
+ e->m_split_checks.push_back(std::make_pair(OPtr<Flag>(&f1), OPtr<Flag>(&f2)));
+ e->rebalance_supply(); // the real split-checking is done during rebalance
+}
+
+void Economy::_check_splits() {
+ Editor_Game_Base& egbase = owner().egbase();
+ Map& map = egbase.map();
+
+ while (m_split_checks.size()) {
+ Flag* f1 = m_split_checks.back().first.get(egbase);
+ Flag* f2 = m_split_checks.back().second.get(egbase);
+ m_split_checks.pop_back();
+
+ if (!f1 || !f2) {
+ if (!f1 && !f2)
+ continue;
+ if (!f1)
+ f1 = f2;
+ if (f1->get_economy() != this)
+ continue;
+
+ // Handle the case when two or more roads are removed simultaneously
+ RouteAStar<AStarZeroEstimator> astar(*m_router, wwWORKER, AStarZeroEstimator());
+ astar.push(*f1);
+ std::set<OPtr<Flag> > reachable;
+ while (RoutingNode* current = astar.step())
+ reachable.insert(¤t->base_flag());
+ if (reachable.size() != m_flags.size())
+ _split(reachable);
+ continue;
+ }
+
+ // If one (or both) of the flags have already been split off, we do not need to re-check
+ if (f1->get_economy() != this || f2->get_economy() != this)
+ continue;
+
+ // Start an A-star searches from f1 with a heuristic bias towards f2,
+ // because we do not need to do anything if f1 is still connected to f2.
+ // If f2 is not reached by the search, split off all the nodes that have been
+ // reached from f1. These nodes induce a connected subgraph.
+ // This means that the newly created economy, which contains all the
+ // flags that have been split, is already connected.
+ RouteAStar<AStarEstimator> astar(*m_router, wwWORKER, AStarEstimator(map, *f2));
+ astar.push(*f1);
+ std::set<OPtr<Flag> > reachable;
+
+ for (;;) {
+ RoutingNode* current = astar.step();
+ if (!current) {
+ _split(reachable);
+ break;
+ } else if (current == f2)
+ break;
+ reachable.insert(¤t->base_flag());
+ }
+ }
+}
/**
* Calculate a route between two flags.
@@ -196,23 +183,21 @@
* This functionality has been moved to Router(). This is currently
* merely a delegator.
*/
-bool Economy::find_route
- (Flag & start, Flag & end,
- Route * const route,
- WareWorker const type,
- int32_t const cost_cutoff)
-{
- assert(start.get_economy() == this);
- assert(end .get_economy() == this);
-
- Map & map = owner().egbase().map();
-
- return
- m_router->find_route(start, end, route, type, cost_cutoff, map);
+bool Economy::find_route(Flag& start,
+ Flag& end,
+ Route* const route,
+ WareWorker const type,
+ int32_t const cost_cutoff) {
+ assert(start.get_economy() == this);
+ assert(end.get_economy() == this);
+
+ Map& map = owner().egbase().map();
+
+ return m_router->find_route(start, end, route, type, cost_cutoff, map);
}
struct ZeroEstimator {
- int32_t operator()(RoutingNode & /* node */) const {return 0;}
+ int32_t operator()(RoutingNode& /* node */) const { return 0; }
};
/**
@@ -227,91 +212,85 @@
* \param cost_cutoff if positive, find paths of at most
* that length (in milliseconds)
*/
-Warehouse * Economy::find_closest_warehouse
- (Flag & start, WareWorker type, Route * route, uint32_t cost_cutoff,
- const Economy::WarehouseAcceptFn & acceptfn)
-{
- if (!warehouses().size())
- return 0;
-
- // A-star with zero estimator = Dijkstra
- RouteAStar<ZeroEstimator> astar(*m_router, type);
- astar.push(start);
-
- while (RoutingNode * current = astar.step()) {
- if
- (cost_cutoff && current->mpf_realcost >
- static_cast<int32_t>(cost_cutoff))
- return 0;
-
- Flag & flag = current->base_flag();
- if (upcast(Warehouse, warehouse, flag.get_building())) {
- if (!acceptfn || acceptfn(*warehouse)) {
- if (route)
- astar.routeto(flag, *route);
- return warehouse;
- }
- }
- }
-
- return 0;
+Warehouse* Economy::find_closest_warehouse(Flag& start,
+ WareWorker type,
+ Route* route,
+ uint32_t cost_cutoff,
+ const Economy::WarehouseAcceptFn& acceptfn) {
+ if (!warehouses().size())
+ return 0;
+
+ // A-star with zero estimator = Dijkstra
+ RouteAStar<ZeroEstimator> astar(*m_router, type);
+ astar.push(start);
+
+ while (RoutingNode* current = astar.step()) {
+ if (cost_cutoff && current->mpf_realcost > static_cast<int32_t>(cost_cutoff))
+ return 0;
+
+ Flag& flag = current->base_flag();
+ if (upcast(Warehouse, warehouse, flag.get_building())) {
+ if (!acceptfn || acceptfn(*warehouse)) {
+ if (route)
+ astar.routeto(flag, *route);
+ return warehouse;
+ }
+ }
+ }
+
+ return 0;
}
-
/**
* Add a flag to the flag array.
* Only call from Flag init and split/merger code!
*/
-void Economy::add_flag(Flag & flag)
-{
- assert(flag.get_economy() == 0);
-
- m_flags.push_back(&flag);
- flag.set_economy(this);
-
- flag.reset_path_finding_cycle();
+void Economy::add_flag(Flag& flag) {
+ assert(flag.get_economy() == 0);
+
+ m_flags.push_back(&flag);
+ flag.set_economy(this);
+
+ flag.reset_path_finding_cycle();
}
/**
* Remove a flag from the flag array.
* Only call from Flag cleanup and split/merger code!
*/
-void Economy::remove_flag(Flag & flag)
-{
- assert(flag.get_economy() == this);
-
- _remove_flag(flag);
-
- // automatically delete the economy when it becomes empty.
- if (m_flags.empty())
- delete this;
+void Economy::remove_flag(Flag& flag) {
+ assert(flag.get_economy() == this);
+
+ _remove_flag(flag);
+
+ // automatically delete the economy when it becomes empty.
+ if (m_flags.empty())
+ delete this;
}
/**
* Remove the flag, but don't delete the economy automatically.
* This is called from the merge code.
*/
-void Economy::_remove_flag(Flag & flag)
-{
- flag.set_economy(0);
+void Economy::_remove_flag(Flag& flag) {
+ flag.set_economy(0);
- // fast remove
- container_iterate(Flags, m_flags, i)
- if (*i.current == &flag) {
- *i.current = *(i.get_end() - 1);
- return m_flags.pop_back();
- }
- throw wexception("trying to remove nonexistent flag");
+ // fast remove
+ container_iterate(Flags, m_flags, i)
+ if (*i.current == &flag) {
+ *i.current = *(i.get_end() - 1);
+ return m_flags.pop_back();
+ }
+ throw wexception("trying to remove nonexistent flag");
}
/**
* Callback for the incredibly rare case that the \ref Router pathfinding
* cycle wraps around.
*/
-void Economy::_reset_all_pathfinding_cycles()
-{
- container_iterate(Flags, m_flags, i)
- (*i.current)->reset_path_finding_cycle();
+void Economy::_reset_all_pathfinding_cycles() {
+ container_iterate(Flags, m_flags, i)
+ (*i.current)->reset_path_finding_cycle();
}
/**
@@ -321,27 +300,21 @@
*
* This is called from Cmd_ResetTargetQuantity and Cmd_SetTargetQuantity
*/
-void Economy::set_ware_target_quantity
- (Ware_Index const ware_type,
- uint32_t const permanent,
- Time const mod_time)
-{
- Target_Quantity & tq = m_ware_target_quantities[ware_type.value()];
- tq.permanent = permanent;
- tq.last_modified = mod_time;
-}
-
-
-void Economy::set_worker_target_quantity
- (Ware_Index const ware_type,
- uint32_t const permanent,
- Time const mod_time)
-{
- Target_Quantity & tq = m_worker_target_quantities[ware_type.value()];
- tq.permanent = permanent;
- tq.last_modified = mod_time;
-}
-
+void Economy::set_ware_target_quantity(Ware_Index const ware_type,
+ uint32_t const permanent,
+ Time const mod_time) {
+ Target_Quantity& tq = m_ware_target_quantities[ware_type.value()];
+ tq.permanent = permanent;
+ tq.last_modified = mod_time;
+}
+
+void Economy::set_worker_target_quantity(Ware_Index const ware_type,
+ uint32_t const permanent,
+ Time const mod_time) {
+ Target_Quantity& tq = m_worker_target_quantities[ware_type.value()];
+ tq.permanent = permanent;
+ tq.last_modified = mod_time;
+}
/**
* Call this whenever some entity created a ware, e.g. when a lumberjack
@@ -349,23 +322,21 @@
* This is also called when a ware is added to the economy through trade or
* a merger.
*/
-void Economy::add_wares(Ware_Index const id, uint32_t const count)
-{
- //log("%p: add(%i, %i)\n", this, id, count);
-
- m_wares.add(id, count);
- _start_request_timer();
-
- // TODO: add to global player inventory?
+void Economy::add_wares(Ware_Index const id, uint32_t const count) {
+ //log("%p: add(%i, %i)\n", this, id, count);
+
+ m_wares.add(id, count);
+ _start_request_timer();
+
+ // TODO: add to global player inventory?
}
-void Economy::add_workers(Ware_Index const id, uint32_t const count)
-{
- //log("%p: add(%i, %i)\n", this, id, count);
-
- m_workers.add(id, count);
- _start_request_timer();
-
- // TODO: add to global player inventory?
+void Economy::add_workers(Ware_Index const id, uint32_t const count) {
+ //log("%p: add(%i, %i)\n", this, id, count);
+
+ m_workers.add(id, count);
+ _start_request_timer();
+
+ // TODO: add to global player inventory?
}
/**
@@ -374,14 +345,13 @@
* This is also called when a ware is removed from the economy through trade or
* a split of the Economy.
*/
-void Economy::remove_wares(Ware_Index const id, uint32_t const count)
-{
- assert(id < m_owner.tribe().get_nrwares());
- //log("%p: remove(%i, %i) from %i\n", this, id, count, m_wares.stock(id));
-
- m_wares.remove(id, count);
-
- // TODO: remove from global player inventory?
+void Economy::remove_wares(Ware_Index const id, uint32_t const count) {
+ assert(id < m_owner.tribe().get_nrwares());
+ //log("%p: remove(%i, %i) from %i\n", this, id, count, m_wares.stock(id));
+
+ m_wares.remove(id, count);
+
+ // TODO: remove from global player inventory?
}
/**
@@ -389,13 +359,12 @@
* This is also called when a worker is removed from the economy through
* a split of the Economy.
*/
-void Economy::remove_workers(Ware_Index const id, uint32_t const count)
-{
- //log("%p: remove(%i, %i) from %i\n", this, id, count, m_workers.stock(id));
-
- m_workers.remove(id, count);
-
- // TODO: remove from global player inventory?
+void Economy::remove_workers(Ware_Index const id, uint32_t const count) {
+ //log("%p: remove(%i, %i) from %i\n", this, id, count, m_workers.stock(id));
+
+ m_workers.remove(id, count);
+
+ // TODO: remove from global player inventory?
}
/**
@@ -403,622 +372,564 @@
* This also adds the wares in the warehouse to the economy. However, if wares
* are added to the warehouse in the future, add_wares() must be called.
*/
-void Economy::add_warehouse(Warehouse & wh)
-{
- m_warehouses.push_back(&wh);
-}
+void Economy::add_warehouse(Warehouse& wh) { m_warehouses.push_back(&wh); }
/**
* Remove the warehouse and its wares from the economy.
*/
-void Economy::remove_warehouse(Warehouse & wh)
-{
- for (size_t i = 0; i < m_warehouses.size(); ++i)
- if (m_warehouses[i] == &wh) {
- m_warehouses[i] = *m_warehouses.rbegin();
- m_warehouses.pop_back();
- return;
- }
-
-
- // This assert was modified, since on loading, warehouses might try to
- // remove themselves from their own economy, though they weren't added
- // (since they weren't initialized)
- assert(m_warehouses.empty());
+void Economy::remove_warehouse(Warehouse& wh) {
+ for (size_t i = 0; i < m_warehouses.size(); ++i)
+ if (m_warehouses[i] == &wh) {
+ m_warehouses[i] = *m_warehouses.rbegin();
+ m_warehouses.pop_back();
+ return;
+ }
+
+ // This assert was modified, since on loading, warehouses might try to
+ // remove themselves from their own economy, though they weren't added
+ // (since they weren't initialized)
+ assert(m_warehouses.empty());
}
/**
* Consider the request, try to fulfill it immediately or queue it for later.
* Important: This must only be called by the \ref Request class.
*/
-void Economy::add_request(Request & req)
-{
- assert(req.is_open());
- assert(!_has_request(req));
-
- assert(&owner());
-
- m_requests.push_back(&req);
-
- // Try to fulfill the request
- _start_request_timer();
+void Economy::add_request(Request& req) {
+ assert(req.is_open());
+ assert(!_has_request(req));
+
+ assert(&owner());
+
+ m_requests.push_back(&req);
+
+ // Try to fulfill the request
+ _start_request_timer();
}
/**
* \return true if the given Request is registered with the \ref Economy, false
* otherwise
*/
-bool Economy::_has_request(Request & req)
-{
- return
- std::find(m_requests.begin(), m_requests.end(), &req)
- !=
- m_requests.end();
+bool Economy::_has_request(Request& req) {
+ return std::find(m_requests.begin(), m_requests.end(), &req) != m_requests.end();
}
/**
* Remove the request from this economy.
* Important: This must only be called by the \ref Request class.
*/
-void Economy::remove_request(Request & req)
-{
- RequestList::iterator const it =
- std::find(m_requests.begin(), m_requests.end(), &req);
-
- if (it == m_requests.end()) {
- log("WARNING: remove_request(%p) not in list\n", &req);
- return;
- }
-
- *it = *m_requests.rbegin();
-
- m_requests.pop_back();
+void Economy::remove_request(Request& req) {
+ RequestList::iterator const it = std::find(m_requests.begin(), m_requests.end(), &req);
+
+ if (it == m_requests.end()) {
+ log("WARNING: remove_request(%p) not in list\n", &req);
+ return;
+ }
+
+ *it = *m_requests.rbegin();
+
+ m_requests.pop_back();
}
/**
* Add a supply to our list of supplies.
*/
-void Economy::add_supply(Supply & supply)
-{
- m_supplies.add_supply(supply);
- _start_request_timer();
+void Economy::add_supply(Supply& supply) {
+ m_supplies.add_supply(supply);
+ _start_request_timer();
}
-
/**
* Remove a supply from our list of supplies.
*/
-void Economy::remove_supply(Supply & supply)
-{
- m_supplies.remove_supply(supply);
-}
-
+void Economy::remove_supply(Supply& supply) { m_supplies.remove_supply(supply); }
bool Economy::needs_ware(Ware_Index const ware_type) const {
- uint32_t const t = ware_target_quantity(ware_type).permanent;
- uint32_t quantity = 0;
- container_iterate_const(std::vector<Warehouse *>, m_warehouses, wh) {
- quantity += (*wh)->get_wares().stock(ware_type);
- if (t <= quantity)
- return false;
- }
- return true;
+ uint32_t const t = ware_target_quantity(ware_type).permanent;
+ uint32_t quantity = 0;
+ container_iterate_const(std::vector<Warehouse*>, m_warehouses, wh) {
+ quantity += (*wh)->get_wares().stock(ware_type);
+ if (t <= quantity)
+ return false;
+ }
+ return true;
}
-
bool Economy::needs_worker(Ware_Index const worker_type) const {
- uint32_t const t = worker_target_quantity(worker_type).permanent;
- uint32_t quantity = 0;
- container_iterate_const(std::vector<Warehouse *>, m_warehouses, wh) {
- quantity += (*wh)->get_workers().stock(worker_type);
- if (t <= quantity)
- return false;
- }
- return true;
+ uint32_t const t = worker_target_quantity(worker_type).permanent;
+ uint32_t quantity = 0;
+ container_iterate_const(std::vector<Warehouse*>, m_warehouses, wh) {
+ quantity += (*wh)->get_workers().stock(worker_type);
+ if (t <= quantity)
+ return false;
+ }
+ return true;
}
-
/**
* Add e's flags to this economy.
*
* Also transfer all wares and wares request. Try to resolve the new ware
* requests if possible.
*/
-void Economy::_merge(Economy & e)
-{
- for (Ware_Index::value_t i = m_owner.tribe().get_nrwares().value(); i;) {
- --i;
- Target_Quantity other_tq = e.m_ware_target_quantities[i];
- Target_Quantity & this_tq = m_ware_target_quantities[i];
- if (this_tq.last_modified < other_tq.last_modified)
- this_tq = other_tq;
- }
- for (Ware_Index::value_t i = m_owner.tribe().get_nrworkers().value(); i;) {
- --i;
- Target_Quantity other_tq = e.m_worker_target_quantities[i];
- Target_Quantity & this_tq = m_worker_target_quantities[i];
- if (this_tq.last_modified < other_tq.last_modified)
- this_tq = other_tq;
- }
-
- // If the options window for e is open, but not the one for *this, the user
- // should still have an options window after the merge. Create an options
- // window for *this where the options window for e is, to give the user
- // some continuity.
- if
- (e.m_optionswindow_registry.window and
- not m_optionswindow_registry.window)
- {
- m_optionswindow_registry.x = e.m_optionswindow_registry.x;
- m_optionswindow_registry.y = e.m_optionswindow_registry.y;
- show_options_window();
- }
-
- for (std::vector<Flag *>::size_type i = e.get_nrflags() + 1; --i;) {
- assert(i == e.get_nrflags());
-
- Flag & flag = *e.m_flags[0];
-
- e._remove_flag(flag); // do not delete other economy yet!
- add_flag(flag);
- }
-
- // Remember that the other economy may not have been connected before the merge
- m_split_checks.insert(m_split_checks.end(), e.m_split_checks.begin(), e.m_split_checks.end());
-
- // implicitly delete the economy
- delete &e;
+void Economy::_merge(Economy& e) {
+ for (Ware_Index::value_t i = m_owner.tribe().get_nrwares().value(); i;) {
+ --i;
+ Target_Quantity other_tq = e.m_ware_target_quantities[i];
+ Target_Quantity& this_tq = m_ware_target_quantities[i];
+ if (this_tq.last_modified < other_tq.last_modified)
+ this_tq = other_tq;
+ }
+ for (Ware_Index::value_t i = m_owner.tribe().get_nrworkers().value(); i;) {
+ --i;
+ Target_Quantity other_tq = e.m_worker_target_quantities[i];
+ Target_Quantity& this_tq = m_worker_target_quantities[i];
+ if (this_tq.last_modified < other_tq.last_modified)
+ this_tq = other_tq;
+ }
+
+ // If the options window for e is open, but not the one for *this, the user
+ // should still have an options window after the merge. Create an options
+ // window for *this where the options window for e is, to give the user
+ // some continuity.
+ if (e.m_optionswindow_registry.window and not m_optionswindow_registry.window) {
+ m_optionswindow_registry.x = e.m_optionswindow_registry.x;
+ m_optionswindow_registry.y = e.m_optionswindow_registry.y;
+ show_options_window();
+ }
+
+ for (std::vector<Flag*>::size_type i = e.get_nrflags() + 1; --i;) {
+ assert(i == e.get_nrflags());
+
+ Flag& flag = *e.m_flags[0];
+
+ e._remove_flag(flag); // do not delete other economy yet!
+ add_flag(flag);
+ }
+
+ // Remember that the other economy may not have been connected before the merge
+ m_split_checks.insert(m_split_checks.end(), e.m_split_checks.begin(), e.m_split_checks.end());
+
+ // implicitly delete the economy
+ delete &e;
}
/**
* Split the given set of flags off into a new economy.
*/
-void Economy::_split(const std::set<OPtr<Flag> > & flags)
-{
- assert(!flags.empty());
-
- Economy & e = *new Economy(m_owner);
-
- for (Ware_Index::value_t i = m_owner.tribe().get_nrwares ().value(); i;) {
- --i;
- e.m_ware_target_quantities[i] = m_ware_target_quantities[i];
- }
- for (Ware_Index::value_t i = m_owner.tribe().get_nrworkers().value(); i;) {
- --i;
- e.m_worker_target_quantities[i] = m_worker_target_quantities[i];
- }
-
- container_iterate_const(std::set<OPtr<Flag> >, flags, it) {
- Flag & flag = *it.current->get(owner().egbase());
- remove_flag(flag);
- e.add_flag(flag);
- }
-
- // As long as rebalance commands are tied to specific flags, we
- // need this, because the flag that rebalance commands for us were
- // tied to might have been moved into the other economy
- _start_request_timer();
+void Economy::_split(const std::set<OPtr<Flag> >& flags) {
+ assert(!flags.empty());
+
+ Economy& e = *new Economy(m_owner);
+
+ for (Ware_Index::value_t i = m_owner.tribe().get_nrwares().value(); i;) {
+ --i;
+ e.m_ware_target_quantities[i] = m_ware_target_quantities[i];
+ }
+ for (Ware_Index::value_t i = m_owner.tribe().get_nrworkers().value(); i;) {
+ --i;
+ e.m_worker_target_quantities[i] = m_worker_target_quantities[i];
+ }
+
+ container_iterate_const(std::set<OPtr<Flag> >, flags, it) {
+ Flag& flag = *it.current->get(owner().egbase());
+ remove_flag(flag);
+ e.add_flag(flag);
+ }
+
+ // As long as rebalance commands are tied to specific flags, we
+ // need this, because the flag that rebalance commands for us were
+ // tied to might have been moved into the other economy
+ _start_request_timer();
}
/**
* Make sure the request timer is running.
*/
-void Economy::_start_request_timer(int32_t const delta)
-{
- if (upcast(Game, game, &m_owner.egbase()))
- game->cmdqueue().enqueue
- (new Cmd_Call_Economy_Balance
- (game->get_gametime() + delta, this, m_request_timerid));
+void Economy::_start_request_timer(int32_t const delta) {
+ if (upcast(Game, game, &m_owner.egbase()))
+ game->cmdqueue().enqueue(
+ new Cmd_Call_Economy_Balance(game->get_gametime() + delta, this, m_request_timerid));
}
-
/**
* Find the supply that is best suited to fulfill the given request.
* \return 0 if no supply is found, the best supply otherwise
*/
-Supply * Economy::_find_best_supply
- (Game & game, const Request & req, int32_t & cost)
-{
- assert(req.is_open());
-
- Route buf_route0, buf_route1;
- Supply * best_supply = 0;
- Route * best_route = 0;
- int32_t best_cost = -1;
- Flag & target_flag = req.target_flag();
-
- for (size_t i = 0; i < m_supplies.get_nrsupplies(); ++i) {
- Supply & supp = m_supplies[i];
-
- // Check requirements
- if (!supp.nr_supplies(game, req))
- continue;
-
- Route * const route =
- best_route != &buf_route0 ? &buf_route0 : &buf_route1;
- // will be cleared by find_route()
-
- if
- (!
- find_route
- (supp.get_position(game)->base_flag(),
- target_flag,
- route,
- req.get_type(),
- best_cost))
- {
- if (!best_route)
- throw wexception
- ("Economy::find_best_supply: COULD NOT FIND A ROUTE!");
- continue;
- }
-
- best_supply = &supp;
- best_route = route;
- best_cost = route->get_totalcost();
- }
-
- if (!best_route)
- return 0;
-
- cost = best_cost;
- return best_supply;
+Supply* Economy::_find_best_supply(Game& game, const Request& req, int32_t& cost) {
+ assert(req.is_open());
+
+ Route buf_route0, buf_route1;
+ Supply* best_supply = 0;
+ Route* best_route = 0;
+ int32_t best_cost = -1;
+ Flag& target_flag = req.target_flag();
+
+ for (size_t i = 0; i < m_supplies.get_nrsupplies(); ++i) {
+ Supply& supp = m_supplies[i];
+
+ // Check requirements
+ if (!supp.nr_supplies(game, req))
+ continue;
+
+ Route* const route = best_route != &buf_route0 ? &buf_route0 : &buf_route1;
+ // will be cleared by find_route()
+
+ if (!find_route(supp.get_position(game)->base_flag(),
+ target_flag,
+ route,
+ req.get_type(),
+ best_cost)) {
+ if (!best_route)
+ throw wexception("Economy::find_best_supply: COULD NOT FIND A ROUTE!");
+ continue;
+ }
+
+ best_supply = &supp;
+ best_route = route;
+ best_cost = route->get_totalcost();
+ }
+
+ if (!best_route)
+ return 0;
+
+ cost = best_cost;
+ return best_supply;
}
struct RequestSupplyPair {
- TrackPtr<Request> request;
- TrackPtr<Supply> supply;
- int32_t priority;
-
- /**
- * pairid is an explicit tie-breaker for comparison.
- *
- * Without it, the pair priority queue would use an implicit, system
- * dependent tie breaker, which in turn causes desyncs.
- */
- uint32_t pairid;
-
- struct Compare {
- bool operator()
- (const RequestSupplyPair & p1, const RequestSupplyPair & p2)
- {
- return
- p1.priority == p2.priority ? p1.pairid < p2.pairid :
- p1.priority < p2.priority;
- }
- };
+ TrackPtr<Request> request;
+ TrackPtr<Supply> supply;
+ int32_t priority;
+
+ /**
+ * pairid is an explicit tie-breaker for comparison.
+ *
+ * Without it, the pair priority queue would use an implicit, system
+ * dependent tie breaker, which in turn causes desyncs.
+ */
+ uint32_t pairid;
+
+ struct Compare {
+ bool operator()(const RequestSupplyPair& p1, const RequestSupplyPair& p2) {
+ return p1.priority == p2.priority ? p1.pairid < p2.pairid : p1.priority < p2.priority;
+ }
+ };
};
-typedef
- std::priority_queue
- <RequestSupplyPair,
- std::vector<RequestSupplyPair>,
- RequestSupplyPair::Compare>
- RSPairQueue;
+typedef std::priority_queue<RequestSupplyPair,
+ std::vector<RequestSupplyPair>,
+ RequestSupplyPair::Compare> RSPairQueue;
struct RSPairStruct {
- RSPairQueue queue;
- uint32_t pairid;
- int32_t nexttimer;
+ RSPairQueue queue;
+ uint32_t pairid;
+ int32_t nexttimer;
- RSPairStruct() : pairid(0), nexttimer(0) {}
+ RSPairStruct() : pairid(0), nexttimer(0) {}
};
/**
* Walk all Requests and find potential transfer candidates.
*/
-void Economy::_process_requests(Game & game, RSPairStruct & s)
-{
- container_iterate_const(RequestList, m_requests, i) {
- Request & req = **i.current;
-
- // We somehow get desynced request lists that don't trigger desync
- // alerts, so add info to the sync stream here.
- {
- ::StreamWrite & ss = game.syncstream();
- ss.Unsigned8 (req.get_type ());
- ss.Unsigned8 (req.get_index ().value());
- ss.Unsigned32(req.target ().serial());
- }
-
- int32_t cost; // estimated time in milliseconds to fulfill Request
- Supply * const supp = _find_best_supply(game, req, cost);
-
- if (!supp)
- continue;
-
- if (!supp->is_active()) {
- // Calculate the time the building will be forced to idle waiting
- // for the request
- int32_t const idletime =
- game.get_gametime() + 15000 + 2 * cost - req.get_required_time();
- // If the building wouldn't have to idle, we wait with the request
- if (idletime < -200) {
- if (s.nexttimer < 0 || s.nexttimer > -idletime)
- s.nexttimer = -idletime;
-
- continue;
- }
- }
-
- int32_t const priority = req.get_priority (cost);
- if (priority < 0)
- continue;
-
- // Otherwise, consider this request/supply pair for queueing
- RequestSupplyPair rsp;
- rsp.request = &req;
- rsp.supply = supp;
- rsp.priority = priority;
- rsp.pairid = ++s.pairid;
-
- s.queue.push(rsp);
- }
+void Economy::_process_requests(Game& game, RSPairStruct& s) {
+ container_iterate_const(RequestList, m_requests, i) {
+ Request& req = **i.current;
+
+ // We somehow get desynced request lists that don't trigger desync
+ // alerts, so add info to the sync stream here.
+ {
+ ::StreamWrite& ss = game.syncstream();
+ ss.Unsigned8(req.get_type());
+ ss.Unsigned8(req.get_index().value());
+ ss.Unsigned32(req.target().serial());
+ }
+
+ int32_t cost; // estimated time in milliseconds to fulfill Request
+ Supply* const supp = _find_best_supply(game, req, cost);
+
+ if (!supp)
+ continue;
+
+ if (!supp->is_active()) {
+ // Calculate the time the building will be forced to idle waiting
+ // for the request
+ int32_t const idletime = game.get_gametime() + 15000 + 2 * cost - req.get_required_time();
+ // If the building wouldn't have to idle, we wait with the request
+ if (idletime < -200) {
+ if (s.nexttimer < 0 || s.nexttimer > -idletime)
+ s.nexttimer = -idletime;
+
+ continue;
+ }
+ }
+
+ int32_t const priority = req.get_priority(cost);
+ if (priority < 0)
+ continue;
+
+ // Otherwise, consider this request/supply pair for queueing
+ RequestSupplyPair rsp;
+ rsp.request = &req;
+ rsp.supply = supp;
+ rsp.priority = priority;
+ rsp.pairid = ++s.pairid;
+
+ s.queue.push(rsp);
+ }
}
/**
* Try to fulfill open requests with available supplies.
*/
-void Economy::_balance_requestsupply(Game & game)
-{
- RSPairStruct rsps;
- rsps.nexttimer = -1;
-
- // Try to fulfill Requests.
- _process_requests(game, rsps);
-
- // Now execute request/supply pairs.
- while (!rsps.queue.empty()) {
- RequestSupplyPair rsp = rsps.queue.top();
-
- rsps.queue.pop();
-
- if
- (!rsp.request ||
- !rsp.supply ||
- !_has_request(*rsp.request) ||
- !rsp.supply->nr_supplies(game, *rsp.request))
- {
- rsps.nexttimer = 200;
- continue;
- }
-
- rsp.request->start_transfer(game, *rsp.supply);
- rsp.request->set_last_request_time(game.get_gametime());
-
- // for multiple wares
- if (rsp.request && _has_request(*rsp.request))
- rsps.nexttimer = 200;
- }
-
- if (rsps.nexttimer > 0) // restart the timer, if necessary
- _start_request_timer(rsps.nexttimer);
+void Economy::_balance_requestsupply(Game& game) {
+ RSPairStruct rsps;
+ rsps.nexttimer = -1;
+
+ // Try to fulfill Requests.
+ _process_requests(game, rsps);
+
+ // Now execute request/supply pairs.
+ while (!rsps.queue.empty()) {
+ RequestSupplyPair rsp = rsps.queue.top();
+
+ rsps.queue.pop();
+
+ if (!rsp.request || !rsp.supply || !_has_request(*rsp.request) ||
+ !rsp.supply->nr_supplies(game, *rsp.request)) {
+ rsps.nexttimer = 200;
+ continue;
+ }
+
+ rsp.request->start_transfer(game, *rsp.supply);
+ rsp.request->set_last_request_time(game.get_gametime());
+
+ // for multiple wares
+ if (rsp.request && _has_request(*rsp.request))
+ rsps.nexttimer = 200;
+ }
+
+ if (rsps.nexttimer > 0) // restart the timer, if necessary
+ _start_request_timer(rsps.nexttimer);
}
/**
* Check whether there is a supply for the given request. If the request is a
* worker request without supply, attempt to create a new worker in a warehouse.
*/
-void Economy::_create_requested_worker(Game & game, Ware_Index index)
-{
- unsigned demand = 0;
-
- container_iterate_const(RequestList, m_requests, j) {
- const Request & req = **j.current;
-
- if (req.get_type() != wwWORKER || req.get_index() != index)
- continue;
-
- // need to check for each request separately, because esp. soldier
- // requests have different specific requirements
- if (m_supplies.have_supplies(game, req))
- continue;
-
- demand += req.get_open_count();
- }
-
- if (!demand)
- return;
-
- // We have worker demand that is not fulfilled by supplies
- // Find warehouses where we can create the required workers,
- // and collect stats about existing build prerequisites
- const Tribe_Descr & tribe = owner().tribe();
- const Worker_Descr & w_desc = *tribe.get_worker_descr(index);
- const Worker_Descr::Buildcost & cost = w_desc.buildcost();
- std::vector<uint32_t> total_available;
- uint32_t total_planned = 0;
-
- total_available.insert(total_available.begin(), cost.size(), 0);
-
- for (uint32_t n_wh = 0; n_wh < warehouses().size(); ++n_wh) {
- Warehouse * wh = m_warehouses[n_wh];
-
- uint32_t planned = wh->get_planned_workers(game, index);
- total_planned += planned;
-
- while (wh->can_create_worker(game, index)) {
- wh->create_worker(game, index);
- if (!--demand)
- return;
- }
-
- std::vector<uint32_t> wh_available =
- wh->calc_available_for_worker(game, index);
- assert(wh_available.size() == total_available.size());
-
- for (uint32_t idx = 0; idx < total_available.size(); ++idx)
- total_available[idx] += wh_available[idx];
- }
-
- // Couldn't create enough workers now.
- // Let's see how many we have resources for that may be scattered
- // throughout the economy.
- uint32_t can_create = std::numeric_limits<uint32_t>::max();
- uint32_t idx = 0;
- uint32_t scarcest_idx = 0;
- container_iterate_const(Worker_Descr::Buildcost, cost, bc) {
- uint32_t cc = total_available[idx] / bc.current->second;
- if (cc <= can_create) {
- scarcest_idx = idx;
- can_create = cc;
- }
- idx++;
- }
-
- if (total_planned > can_create) {
- // Eliminate some excessive plans, to make sure we never request more than
- // there are supplies for (otherwise, cyclic transportation might happen)
- // Note that supplies might suddenly disappear outside our control because
- // of loss of land or silly player actions.
- for (uint32_t n_wh = 0; n_wh < warehouses().size(); ++n_wh) {
- Warehouse * wh = m_warehouses[n_wh];
-
- uint32_t planned = wh->get_planned_workers(game, index);
- uint32_t reduce = std::min(planned, total_planned - can_create);
- wh->plan_workers(game, index, planned - reduce);
- total_planned -= reduce;
- }
- } else if (total_planned < demand) {
- uint32_t plan_goal = std::min(can_create, demand);
-
- for (uint32_t n_wh = 0; n_wh < warehouses().size(); ++n_wh) {
- Warehouse * wh = m_warehouses[n_wh];
- uint32_t supply =
- wh->calc_available_for_worker(game, index)[scarcest_idx];
-
- total_planned -= wh->get_planned_workers(game, index);
- uint32_t plan = std::min(supply, plan_goal - total_planned);
- wh->plan_workers(game, index, plan);
- total_planned += plan;
- }
- }
+void Economy::_create_requested_worker(Game& game, Ware_Index index) {
+ unsigned demand = 0;
+
+ container_iterate_const(RequestList, m_requests, j) {
+ const Request& req = **j.current;
+
+ if (req.get_type() != wwWORKER || req.get_index() != index)
+ continue;
+
+ // need to check for each request separately, because esp. soldier
+ // requests have different specific requirements
+ if (m_supplies.have_supplies(game, req))
+ continue;
+
+ demand += req.get_open_count();
+ }
+
+ if (!demand)
+ return;
+
+ // We have worker demand that is not fulfilled by supplies
+ // Find warehouses where we can create the required workers,
+ // and collect stats about existing build prerequisites
+ const Tribe_Descr& tribe = owner().tribe();
+ const Worker_Descr& w_desc = *tribe.get_worker_descr(index);
+ const Worker_Descr::Buildcost& cost = w_desc.buildcost();
+ std::vector<uint32_t> total_available;
+ uint32_t total_planned = 0;
+
+ total_available.insert(total_available.begin(), cost.size(), 0);
+
+ for (uint32_t n_wh = 0; n_wh < warehouses().size(); ++n_wh) {
+ Warehouse* wh = m_warehouses[n_wh];
+
+ uint32_t planned = wh->get_planned_workers(game, index);
+ total_planned += planned;
+
+ while (wh->can_create_worker(game, index)) {
+ wh->create_worker(game, index);
+ if (!--demand)
+ return;
+ }
+
+ std::vector<uint32_t> wh_available = wh->calc_available_for_worker(game, index);
+ assert(wh_available.size() == total_available.size());
+
+ for (uint32_t idx = 0; idx < total_available.size(); ++idx)
+ total_available[idx] += wh_available[idx];
+ }
+
+ // Couldn't create enough workers now.
+ // Let's see how many we have resources for that may be scattered
+ // throughout the economy.
+ uint32_t can_create = std::numeric_limits<uint32_t>::max();
+ uint32_t idx = 0;
+ uint32_t scarcest_idx = 0;
+ container_iterate_const(Worker_Descr::Buildcost, cost, bc) {
+ uint32_t cc = total_available[idx] / bc.current->second;
+ if (cc <= can_create) {
+ scarcest_idx = idx;
+ can_create = cc;
+ }
+ idx++;
+ }
+
+ if (total_planned > can_create) {
+ // Eliminate some excessive plans, to make sure we never request more than
+ // there are supplies for (otherwise, cyclic transportation might happen)
+ // Note that supplies might suddenly disappear outside our control because
+ // of loss of land or silly player actions.
+ for (uint32_t n_wh = 0; n_wh < warehouses().size(); ++n_wh) {
+ Warehouse* wh = m_warehouses[n_wh];
+
+ uint32_t planned = wh->get_planned_workers(game, index);
+ uint32_t reduce = std::min(planned, total_planned - can_create);
+ wh->plan_workers(game, index, planned - reduce);
+ total_planned -= reduce;
+ }
+ } else if (total_planned < demand) {
+ uint32_t plan_goal = std::min(can_create, demand);
+
+ for (uint32_t n_wh = 0; n_wh < warehouses().size(); ++n_wh) {
+ Warehouse* wh = m_warehouses[n_wh];
+ uint32_t supply = wh->calc_available_for_worker(game, index)[scarcest_idx];
+
+ total_planned -= wh->get_planned_workers(game, index);
+ uint32_t plan = std::min(supply, plan_goal - total_planned);
+ wh->plan_workers(game, index, plan);
+ total_planned += plan;
+ }
+ }
}
/**
* Walk all Requests and find requests of workers than aren't supplied. Then
* try to create the worker at warehouses.
*/
-void Economy::_create_requested_workers(Game & game)
-{
- if (!warehouses().size())
- return;
-
- const Tribe_Descr & tribe = owner().tribe();
- for
- (Ware_Index index = Ware_Index::First();
- index < tribe.get_nrworkers(); ++index)
- {
- if (!owner().is_worker_type_allowed(index))
- continue;
- if (!tribe.get_worker_descr(index)->is_buildable())
- continue;
-
- _create_requested_worker(game, index);
- }
+void Economy::_create_requested_workers(Game& game) {
+ if (!warehouses().size())
+ return;
+
+ const Tribe_Descr& tribe = owner().tribe();
+ for (Ware_Index index = Ware_Index::First(); index < tribe.get_nrworkers(); ++index) {
+ if (!owner().is_worker_type_allowed(index))
+ continue;
+ if (!tribe.get_worker_descr(index)->is_buildable())
+ continue;
+
+ _create_requested_worker(game, index);
+ }
}
/**
* Helper function for \ref _handle_active_supplies
*/
-static bool accept_warehouse_if_policy
- (Warehouse & wh, WareWorker type,
- Ware_Index ware, Warehouse::StockPolicy policy)
-{
- return wh.get_stock_policy(type, ware) == policy;
+static bool accept_warehouse_if_policy(Warehouse& wh,
+ WareWorker type,
+ Ware_Index ware,
+ Warehouse::StockPolicy policy) {
+ return wh.get_stock_policy(type, ware) == policy;
}
/**
* Send all active supplies (wares that are outside on the road network without
* being sent to a specific request) to a warehouse.
*/
-void Economy::_handle_active_supplies(Game & game)
-{
- if (!warehouses().size())
- return;
-
- typedef std::vector<std::pair<Supply *, Warehouse *> > Assignments;
- Assignments assignments;
-
- for (uint32_t idx = 0; idx < m_supplies.get_nrsupplies(); ++idx) {
- Supply & supply = m_supplies[idx];
- if (supply.has_storage())
- continue;
-
- WareWorker type;
- Ware_Index ware;
- supply.get_ware_type(type, ware);
-
- bool haveprefer = false;
- bool havenormal = false;
- for (uint32_t nwh = 0; nwh < m_warehouses.size(); ++nwh) {
- Warehouse * wh = m_warehouses[nwh];
- Warehouse::StockPolicy policy = wh->get_stock_policy(type, ware);
- if (policy == Warehouse::SP_Prefer) {
- haveprefer = true;
- break;
- }
- if (policy == Warehouse::SP_Normal)
- havenormal = true;
- }
- if (!havenormal && !haveprefer && type == wwWARE)
- continue;
-
- Warehouse * wh = find_closest_warehouse
- (supply.get_position(game)->base_flag(), type, 0, 0,
- (!haveprefer && !havenormal)
- ?
- WarehouseAcceptFn()
- :
- boost::bind
- (&accept_warehouse_if_policy,
- _1, type, ware,
- haveprefer ? Warehouse::SP_Prefer : Warehouse::SP_Normal));
-
- if (!wh) {
- log
- ("Warning: Economy::_handle_active_supplies "
- "didn't find warehouse\n");
- return;
- }
-
- assignments.push_back(std::make_pair(&supply, wh));
- }
-
- // Actually start with the transfers in a separate second phase,
- // to avoid potential future problems caused by the m_supplies changing
- // under us in some way.
- ::StreamWrite & ss = game.syncstream();
- ss.Unsigned32(0x02decafa); // appears as facade02 in sync stream
- ss.Unsigned32(assignments.size());
-
- container_iterate_const(Assignments, assignments, it) {
- ss.Unsigned32(it.current->first->get_position(game)->serial());
- ss.Unsigned32(it.current->second->serial());
-
- it.current->first->send_to_storage(game, it.current->second);
- }
+void Economy::_handle_active_supplies(Game& game) {
+ if (!warehouses().size())
+ return;
+
+ typedef std::vector<std::pair<Supply*, Warehouse*> > Assignments;
+ Assignments assignments;
+
+ for (uint32_t idx = 0; idx < m_supplies.get_nrsupplies(); ++idx) {
+ Supply& supply = m_supplies[idx];
+ if (supply.has_storage())
+ continue;
+
+ WareWorker type;
+ Ware_Index ware;
+ supply.get_ware_type(type, ware);
+
+ bool haveprefer = false;
+ bool havenormal = false;
+ for (uint32_t nwh = 0; nwh < m_warehouses.size(); ++nwh) {
+ Warehouse* wh = m_warehouses[nwh];
+ Warehouse::StockPolicy policy = wh->get_stock_policy(type, ware);
+ if (policy == Warehouse::SP_Prefer) {
+ haveprefer = true;
+ break;
+ }
+ if (policy == Warehouse::SP_Normal)
+ havenormal = true;
+ }
+ if (!havenormal && !haveprefer && type == wwWARE)
+ continue;
+
+ Warehouse* wh = find_closest_warehouse(
+ supply.get_position(game)->base_flag(),
+ type,
+ 0,
+ 0,
+ (!haveprefer && !havenormal)
+ ? WarehouseAcceptFn()
+ : boost::bind(&accept_warehouse_if_policy,
+ _1,
+ type,
+ ware,
+ haveprefer ? Warehouse::SP_Prefer : Warehouse::SP_Normal));
+
+ if (!wh) {
+ log("Warning: Economy::_handle_active_supplies "
+ "didn't find warehouse\n");
+ return;
+ }
+
+ assignments.push_back(std::make_pair(&supply, wh));
+ }
+
+ // Actually start with the transfers in a separate second phase,
+ // to avoid potential future problems caused by the m_supplies changing
+ // under us in some way.
+ ::StreamWrite& ss = game.syncstream();
+ ss.Unsigned32(0x02decafa); // appears as facade02 in sync stream
+ ss.Unsigned32(assignments.size());
+
+ container_iterate_const(Assignments, assignments, it) {
+ ss.Unsigned32(it.current->first->get_position(game)->serial());
+ ss.Unsigned32(it.current->second->serial());
+
+ it.current->first->send_to_storage(game, it.current->second);
+ }
}
/**
* Balance Requests and Supplies by collecting and weighing pairs, and
* starting transfers for them.
*/
-void Economy::balance(uint32_t const timerid)
-{
- if (m_request_timerid != timerid)
- return;
- ++m_request_timerid;
-
- Game & game = ref_cast<Game, Editor_Game_Base>(owner().egbase());
-
- _check_splits();
-
- _create_requested_workers (game);
-
- _balance_requestsupply(game);
-
- _handle_active_supplies(game);
+void Economy::balance(uint32_t const timerid) {
+ if (m_request_timerid != timerid)
+ return;
+ ++m_request_timerid;
+
+ Game& game = ref_cast<Game, Editor_Game_Base>(owner().egbase());
+
+ _check_splits();
+
+ _create_requested_workers(game);
+
+ _balance_requestsupply(game);
+
+ _handle_active_supplies(game);
}
}
=== modified file 'src/economy/economy.h'
--- src/economy/economy.h 2013-04-22 20:15:00 +0000
+++ src/economy/economy.h 2013-05-18 05:56:27 +0000
@@ -32,7 +32,6 @@
#include "logic/warelist.h"
#include "logic/wareworker.h"
-
namespace Widelands {
struct Player;
struct Game;
@@ -69,162 +68,154 @@
* on the assumption that they are, with fallbacks for when they aren't.
*/
class Economy : boost::noncopyable {
-public:
- friend class EconomyDataPacket;
-
- /// Configurable target quantity for the supply of a ware type in the
- /// economy.
- ///
- /// This affects the result of \ref needs_ware and thereby the demand checks
- /// in production programs. A ware type is considered to be needed if there
- /// are less than the permanent target quantity stored in warehouses in the
- /// economy.
- ///
- /// The last_modified time is used to determine which setting to use when
- /// economies are merged. The setting that was modified most recently will
- /// be used for the merged economy.
- struct Target_Quantity {
- uint32_t permanent;
- Time last_modified;
- };
-
- Economy(Player &);
- ~Economy();
-
- Player & owner() const throw () {return m_owner;}
-
- static void check_merge(Flag &, Flag &);
- static void check_split(Flag &, Flag &);
-
- bool find_route
- (Flag & start, Flag & end,
- Route * route,
- WareWorker type,
- int32_t cost_cutoff = -1);
-
- typedef boost::function<bool (Warehouse &)> WarehouseAcceptFn;
- Warehouse * find_closest_warehouse
- (Flag & start, WareWorker type = wwWORKER, Route * route = 0,
- uint32_t cost_cutoff = 0,
- const WarehouseAcceptFn & acceptfn = WarehouseAcceptFn());
-
- std::vector<Flag *>::size_type get_nrflags() const {return m_flags.size();}
- void add_flag(Flag &);
- void remove_flag(Flag &);
- Flag & get_arbitrary_flag();
-
- void set_ware_target_quantity (Ware_Index, uint32_t, Time);
- void set_worker_target_quantity(Ware_Index, uint32_t, Time);
-
- void add_wares (Ware_Index, uint32_t count = 1);
- void remove_wares (Ware_Index, uint32_t count = 1);
-
- void add_workers(Ware_Index, uint32_t count = 1);
- void remove_workers(Ware_Index, uint32_t count = 1);
-
- void add_warehouse(Warehouse &);
- void remove_warehouse(Warehouse &);
- const std::vector<Warehouse *>& warehouses() const {return m_warehouses;}
-
- void add_request(Request &);
- void remove_request(Request &);
-
- void add_supply(Supply &);
- void remove_supply(Supply &);
-
- /// information about this economy
- WareList::count_type stock_ware (Ware_Index const i) {
- return m_wares .stock(i);
- }
- WareList::count_type stock_worker(Ware_Index const i) {
- return m_workers.stock(i);
- }
-
- /// Whether the economy needs more of this ware type.
- /// Productionsites may ask this before they produce, to avoid depleting a
- /// ware type by overproducing another from it.
- bool needs_ware(Ware_Index) const;
-
- /// Whether the economy needs more of this worker type.
- /// Productionsites may ask this before they produce, to avoid depleting a
- /// ware type by overproducing a worker type from it.
- bool needs_worker(Ware_Index) const;
-
- const Target_Quantity & ware_target_quantity (Ware_Index const i) const {
- return m_ware_target_quantities[i.value()];
- }
- Target_Quantity & ware_target_quantity (Ware_Index const i) {
- return m_ware_target_quantities[i.value()];
- }
- const Target_Quantity & worker_target_quantity(Ware_Index const i) const {
- return m_worker_target_quantities[i.value()];
- }
- Target_Quantity & worker_target_quantity(Ware_Index const i) {
- return m_worker_target_quantities[i.value()];
- }
-
- void show_options_window();
- UI::UniqueWindow::Registry m_optionswindow_registry;
-
-
- const WareList & get_wares () const {return m_wares;}
- const WareList & get_workers() const {return m_workers;}
-
- ///< called by \ref Cmd_Call_Economy_Balance
- void balance(uint32_t timerid);
-
- void rebalance_supply() {_start_request_timer();}
-
-private:
-/*************/
-/* Functions */
-/*************/
- void _remove_flag(Flag &);
- void _reset_all_pathfinding_cycles();
-
- void _merge(Economy &);
- void _check_splits();
- void _split(const std::set<OPtr<Flag> > &);
-
- void _start_request_timer(int32_t delta = 200);
-
- Supply * _find_best_supply(Game &, const Request &, int32_t & cost);
- void _process_requests(Game &, RSPairStruct &);
- void _balance_requestsupply(Game &);
- void _handle_active_supplies(Game &);
- void _create_requested_workers(Game &);
- void _create_requested_worker(Game &, Ware_Index);
-
- bool _has_request(Request &);
-
-/*************/
-/* Variables */
-/*************/
- typedef std::vector<Request *> RequestList;
-
- Player & m_owner;
-
- typedef std::vector<Flag *> Flags;
- Flags m_flags;
- WareList m_wares; ///< virtual storage with all wares in this Economy
- WareList m_workers; ///< virtual storage with all workers in this Economy
- std::vector<Warehouse *> m_warehouses;
-
- RequestList m_requests; ///< requests
- SupplyList m_supplies;
-
- Target_Quantity * m_ware_target_quantities;
- Target_Quantity * m_worker_target_quantities;
- Router * m_router;
-
- typedef std::pair<OPtr<Flag>, OPtr<Flag> > SplitPair;
- std::vector<SplitPair> m_split_checks;
-
- /**
- * ID for the next request balancing timer. Used to throttle
- * excessive calls to the request/supply balancing logic.
- */
- uint32_t m_request_timerid;
+ public:
+ friend class EconomyDataPacket;
+
+ /// Configurable target quantity for the supply of a ware type in the
+ /// economy.
+ ///
+ /// This affects the result of \ref needs_ware and thereby the demand checks
+ /// in production programs. A ware type is considered to be needed if there
+ /// are less than the permanent target quantity stored in warehouses in the
+ /// economy.
+ ///
+ /// The last_modified time is used to determine which setting to use when
+ /// economies are merged. The setting that was modified most recently will
+ /// be used for the merged economy.
+ struct Target_Quantity {
+ uint32_t permanent;
+ Time last_modified;
+ };
+
+ Economy(Player&);
+ ~Economy();
+
+ Player& owner() const throw() { return m_owner; }
+
+ static void check_merge(Flag&, Flag&);
+ static void check_split(Flag&, Flag&);
+
+ bool find_route(Flag& start, Flag& end, Route* route, WareWorker type, int32_t cost_cutoff = -1);
+
+ typedef boost::function<bool(Warehouse&)> WarehouseAcceptFn;
+ Warehouse* find_closest_warehouse(Flag& start,
+ WareWorker type = wwWORKER,
+ Route* route = 0,
+ uint32_t cost_cutoff = 0,
+ const WarehouseAcceptFn& acceptfn = WarehouseAcceptFn());
+
+ std::vector<Flag*>::size_type get_nrflags() const { return m_flags.size(); }
+ void add_flag(Flag&);
+ void remove_flag(Flag&);
+ Flag& get_arbitrary_flag();
+
+ void set_ware_target_quantity(Ware_Index, uint32_t, Time);
+ void set_worker_target_quantity(Ware_Index, uint32_t, Time);
+
+ void add_wares(Ware_Index, uint32_t count = 1);
+ void remove_wares(Ware_Index, uint32_t count = 1);
+
+ void add_workers(Ware_Index, uint32_t count = 1);
+ void remove_workers(Ware_Index, uint32_t count = 1);
+
+ void add_warehouse(Warehouse&);
+ void remove_warehouse(Warehouse&);
+ const std::vector<Warehouse*>& warehouses() const { return m_warehouses; }
+
+ void add_request(Request&);
+ void remove_request(Request&);
+
+ void add_supply(Supply&);
+ void remove_supply(Supply&);
+
+ /// information about this economy
+ WareList::count_type stock_ware(Ware_Index const i) { return m_wares.stock(i); }
+ WareList::count_type stock_worker(Ware_Index const i) { return m_workers.stock(i); }
+
+ /// Whether the economy needs more of this ware type.
+ /// Productionsites may ask this before they produce, to avoid depleting a
+ /// ware type by overproducing another from it.
+ bool needs_ware(Ware_Index) const;
+
+ /// Whether the economy needs more of this worker type.
+ /// Productionsites may ask this before they produce, to avoid depleting a
+ /// ware type by overproducing a worker type from it.
+ bool needs_worker(Ware_Index) const;
+
+ const Target_Quantity& ware_target_quantity(Ware_Index const i) const {
+ return m_ware_target_quantities[i.value()];
+ }
+ Target_Quantity& ware_target_quantity(Ware_Index const i) {
+ return m_ware_target_quantities[i.value()];
+ }
+ const Target_Quantity& worker_target_quantity(Ware_Index const i) const {
+ return m_worker_target_quantities[i.value()];
+ }
+ Target_Quantity& worker_target_quantity(Ware_Index const i) {
+ return m_worker_target_quantities[i.value()];
+ }
+
+ void show_options_window();
+ UI::UniqueWindow::Registry m_optionswindow_registry;
+
+ const WareList& get_wares() const { return m_wares; }
+ const WareList& get_workers() const { return m_workers; }
+
+ ///< called by \ref Cmd_Call_Economy_Balance
+ void balance(uint32_t timerid);
+
+ void rebalance_supply() { _start_request_timer(); }
+
+ private:
+ /*************/
+ /* Functions */
+ /*************/
+ void _remove_flag(Flag&);
+ void _reset_all_pathfinding_cycles();
+
+ void _merge(Economy&);
+ void _check_splits();
+ void _split(const std::set<OPtr<Flag> >&);
+
+ void _start_request_timer(int32_t delta = 200);
+
+ Supply* _find_best_supply(Game&, const Request&, int32_t& cost);
+ void _process_requests(Game&, RSPairStruct&);
+ void _balance_requestsupply(Game&);
+ void _handle_active_supplies(Game&);
+ void _create_requested_workers(Game&);
+ void _create_requested_worker(Game&, Ware_Index);
+
+ bool _has_request(Request&);
+
+ /*************/
+ /* Variables */
+ /*************/
+ typedef std::vector<Request*> RequestList;
+
+ Player& m_owner;
+
+ typedef std::vector<Flag*> Flags;
+ Flags m_flags;
+ WareList m_wares; ///< virtual storage with all wares in this Economy
+ WareList m_workers; ///< virtual storage with all workers in this Economy
+ std::vector<Warehouse*> m_warehouses;
+
+ RequestList m_requests; ///< requests
+ SupplyList m_supplies;
+
+ Target_Quantity* m_ware_target_quantities;
+ Target_Quantity* m_worker_target_quantities;
+ Router* m_router;
+
+ typedef std::pair<OPtr<Flag>, OPtr<Flag> > SplitPair;
+ std::vector<SplitPair> m_split_checks;
+
+ /**
+ * ID for the next request balancing timer. Used to throttle
+ * excessive calls to the request/supply balancing logic.
+ */
+ uint32_t m_request_timerid;
};
}
=== modified file 'src/economy/economy_data_packet.cc'
--- src/economy/economy_data_packet.cc 2013-02-10 19:36:24 +0000
+++ src/economy/economy_data_packet.cc 2013-05-18 05:56:27 +0000
@@ -26,108 +26,95 @@
#include "logic/tribe.h"
#include "logic/player.h"
-
#define CURRENT_ECONOMY_VERSION 3
namespace Widelands {
-void EconomyDataPacket::Read(FileRead & fr)
-{
- uint16_t const version = fr.Unsigned16();
+void EconomyDataPacket::Read(FileRead& fr) {
+ uint16_t const version = fr.Unsigned16();
- try {
- if (1 <= version and version <= CURRENT_ECONOMY_VERSION) {
- if (2 <= version)
- try {
- const Tribe_Descr & tribe = m_eco->owner().tribe();
- while (Time const last_modified = fr.Unsigned32()) {
- char const * const type_name = fr.CString();
- uint32_t const permanent = fr.Unsigned32();
- if (version <= 2)
- fr.Unsigned32();
- if (Ware_Index i = tribe.ware_index(type_name)) {
- if
- (tribe.get_ware_descr(i)->default_target_quantity()
- ==
- std::numeric_limits<uint32_t>::max())
- log
- ("WARNING: target quantity configured for %s, "
- "which should not have target quantity, "
- "ignoring\n",
- type_name);
- else {
- Economy::Target_Quantity & tq =
- m_eco->m_ware_target_quantities[i.value()];
- if (tq.last_modified)
- throw game_data_error
- (_("duplicated entry for %s"), type_name);
- tq.permanent = permanent;
- tq.last_modified = last_modified;
- }
- } else if ((i = tribe.worker_index(type_name))) {
- if
- (tribe.get_worker_descr(i)->default_target_quantity()
- ==
- std::numeric_limits<uint32_t>::max())
- log
- ("WARNING: target quantity configured for %s, "
- "which should not have target quantity, "
- "ignoring\n",
- type_name);
- else {
- Economy::Target_Quantity & tq =
- m_eco->m_worker_target_quantities[i.value()];
- if (tq.last_modified)
- throw game_data_error
- (_("duplicated entry for %s"), type_name);
- tq.permanent = permanent;
- tq.last_modified = last_modified;
- }
- } else
- log
- ("WARNING: target quantity configured for \"%s\", "
- "which is not a ware or worker type defined in tribe "
- "%s, ignoring\n",
- type_name, tribe.name().c_str());
- }
- } catch (const _wexception & e) {
- throw game_data_error(_("target quantities: %s"), e.what());
- }
- m_eco->m_request_timerid = fr.Unsigned32();
- } else {
- throw game_data_error(_("unknown version %u"), version);
- }
- } catch (const std::exception & e) {
- throw game_data_error(_("economy: %s"), e.what());
- }
+ try {
+ if (1 <= version and version <= CURRENT_ECONOMY_VERSION) {
+ if (2 <= version)
+ try {
+ const Tribe_Descr& tribe = m_eco->owner().tribe();
+ while (Time const last_modified = fr.Unsigned32()) {
+ char const* const type_name = fr.CString();
+ uint32_t const permanent = fr.Unsigned32();
+ if (version <= 2)
+ fr.Unsigned32();
+ if (Ware_Index i = tribe.ware_index(type_name)) {
+ if (tribe.get_ware_descr(i)->default_target_quantity() ==
+ std::numeric_limits<uint32_t>::max())
+ log("WARNING: target quantity configured for %s, "
+ "which should not have target quantity, "
+ "ignoring\n",
+ type_name);
+ else {
+ Economy::Target_Quantity& tq = m_eco->m_ware_target_quantities[i.value()];
+ if (tq.last_modified)
+ throw game_data_error(_("duplicated entry for %s"), type_name);
+ tq.permanent = permanent;
+ tq.last_modified = last_modified;
+ }
+ } else if ((i = tribe.worker_index(type_name))) {
+ if (tribe.get_worker_descr(i)->default_target_quantity() ==
+ std::numeric_limits<uint32_t>::max())
+ log("WARNING: target quantity configured for %s, "
+ "which should not have target quantity, "
+ "ignoring\n",
+ type_name);
+ else {
+ Economy::Target_Quantity& tq = m_eco->m_worker_target_quantities[i.value()];
+ if (tq.last_modified)
+ throw game_data_error(_("duplicated entry for %s"), type_name);
+ tq.permanent = permanent;
+ tq.last_modified = last_modified;
+ }
+ } else
+ log("WARNING: target quantity configured for \"%s\", "
+ "which is not a ware or worker type defined in tribe "
+ "%s, ignoring\n",
+ type_name,
+ tribe.name().c_str());
+ }
+ }
+ catch (const _wexception & e) {
+ throw game_data_error(_("target quantities: %s"), e.what());
+ }
+ m_eco->m_request_timerid = fr.Unsigned32();
+ } else {
+ throw game_data_error(_("unknown version %u"), version);
+ }
+ }
+ catch (const std::exception & e) {
+ throw game_data_error(_("economy: %s"), e.what());
+ }
}
-void EconomyDataPacket::Write(FileWrite & fw)
-{
- fw.Unsigned16(CURRENT_ECONOMY_VERSION);
- const Tribe_Descr & tribe = m_eco->owner().tribe();
- for (Ware_Index i = tribe.get_nrwares(); i.value();) {
- --i;
- const Economy::Target_Quantity & tq =
- m_eco->m_ware_target_quantities[i.value()];
- if (Time const last_modified = tq.last_modified) {
- fw.Unsigned32(last_modified);
- fw.CString(tribe.get_ware_descr(i)->name());
- fw.Unsigned32(tq.permanent);
- }
- }
- for (Ware_Index i = tribe.get_nrworkers(); i.value();) {
- --i;
- const Economy::Target_Quantity & tq =
- m_eco->m_worker_target_quantities[i.value()];
- if (Time const last_modified = tq.last_modified) {
- fw.Unsigned32(last_modified);
- fw.CString(tribe.get_worker_descr(i)->name());
- fw.Unsigned32(tq.permanent);
- }
- }
- fw.Unsigned32(0); // terminator
- fw.Unsigned32(m_eco->m_request_timerid);
+void EconomyDataPacket::Write(FileWrite& fw) {
+ fw.Unsigned16(CURRENT_ECONOMY_VERSION);
+ const Tribe_Descr& tribe = m_eco->owner().tribe();
+ for (Ware_Index i = tribe.get_nrwares(); i.value();) {
+ --i;
+ const Economy::Target_Quantity& tq = m_eco->m_ware_target_quantities[i.value()];
+ if (Time const last_modified = tq.last_modified) {
+ fw.Unsigned32(last_modified);
+ fw.CString(tribe.get_ware_descr(i)->name());
+ fw.Unsigned32(tq.permanent);
+ }
+ }
+ for (Ware_Index i = tribe.get_nrworkers(); i.value();) {
+ --i;
+ const Economy::Target_Quantity& tq = m_eco->m_worker_target_quantities[i.value()];
+ if (Time const last_modified = tq.last_modified) {
+ fw.Unsigned32(last_modified);
+ fw.CString(tribe.get_worker_descr(i)->name());
+ fw.Unsigned32(tq.permanent);
+ }
+ }
+ fw.Unsigned32(0); // terminator
+ fw.Unsigned32(m_eco->m_request_timerid);
}
}
=== modified file 'src/economy/economy_data_packet.h'
--- src/economy/economy_data_packet.h 2013-04-22 20:15:00 +0000
+++ src/economy/economy_data_packet.h 2013-05-18 05:56:27 +0000
@@ -30,18 +30,16 @@
struct Map_Map_Object_Saver;
class EconomyDataPacket {
- public:
- EconomyDataPacket(Economy * e) : m_eco(e) {}
-
- void Read(FileRead &);
- void Write(FileWrite &);
-
- private:
- Economy * m_eco;
+ public:
+ EconomyDataPacket(Economy* e) : m_eco(e) {}
+
+ void Read(FileRead&);
+ void Write(FileWrite&);
+
+ private:
+ Economy* m_eco;
};
}
#endif
-
-
=== modified file 'src/economy/flag.cc'
--- src/economy/flag.cc 2013-02-10 19:36:24 +0000
+++ src/economy/flag.cc 2013-05-18 05:56:27 +0000
@@ -45,310 +45,269 @@
/**
* Create the flag. Initially, it doesn't have any attachments.
*/
-Flag::Flag() :
-PlayerImmovable(g_flag_descr),
-m_animstart(0),
-m_building(0),
-m_item_capacity(8),
-m_item_filled(0),
-m_items(new PendingItem[m_item_capacity]),
-m_always_call_for_flag(0)
-{
- for (uint32_t i = 0; i < 6; ++i) m_roads[i] = 0;
+Flag::Flag()
+ : PlayerImmovable(g_flag_descr),
+ m_animstart(0),
+ m_building(0),
+ m_item_capacity(8),
+ m_item_filled(0),
+ m_items(new PendingItem[m_item_capacity]),
+ m_always_call_for_flag(0) {
+ for (uint32_t i = 0; i < 6; ++i)
+ m_roads[i] = 0;
}
/**
* Shouldn't be necessary to do anything, since die() always calls
* cleanup() first.
*/
-Flag::~Flag()
-{
- if (m_item_filled)
- log("Flag: ouch! items left\n");
- delete[] m_items;
-
- if (m_building)
- log("Flag: ouch! building left\n");
-
- if (m_flag_jobs.size())
- log("Flag: ouch! flagjobs left\n");
-
- for (int32_t i = 0; i < 6; ++i)
- if (m_roads[i])
- log("Flag: ouch! road left\n");
+Flag::~Flag() {
+ if (m_item_filled)
+ log("Flag: ouch! items left\n");
+ delete[] m_items;
+
+ if (m_building)
+ log("Flag: ouch! building left\n");
+
+ if (m_flag_jobs.size())
+ log("Flag: ouch! flagjobs left\n");
+
+ for (int32_t i = 0; i < 6; ++i)
+ if (m_roads[i])
+ log("Flag: ouch! road left\n");
}
-void Flag::load_finish(Editor_Game_Base & egbase) {
- CapacityWaitQueue & queue = m_capacity_wait;
- for (wl_range<CapacityWaitQueue > r(queue); r;)
- {
- Worker & worker = *r->get(egbase);
- Bob::State const * const state =
- worker.get_state(Worker::taskWaitforcapacity);
- if (not state)
- log
- ("WARNING: worker %u is in the capacity wait queue of flag %u but "
- "does not have a waitforcapacity task! Removing from queue.\n",
- worker.serial(), serial());
- else if (state->objvar1 != this)
- log
- ("WARNING: worker %u is in the capacity wait queue of flag %u but "
- "its waitforcapacity task is for map object %u! Removing from "
- "queue.\n",
- worker.serial(), serial(), state->objvar1.serial());
- else {
- ++r;
- continue;
- }
- r = wl_erase(queue, r.current);
- }
+void Flag::load_finish(Editor_Game_Base& egbase) {
+ CapacityWaitQueue& queue = m_capacity_wait;
+ for (wl_range<CapacityWaitQueue> r(queue); r;) {
+ Worker& worker = *r->get(egbase);
+ Bob::State const* const state = worker.get_state(Worker::taskWaitforcapacity);
+ if (not state)
+ log("WARNING: worker %u is in the capacity wait queue of flag %u but "
+ "does not have a waitforcapacity task! Removing from queue.\n",
+ worker.serial(),
+ serial());
+ else if (state->objvar1 != this)
+ log("WARNING: worker %u is in the capacity wait queue of flag %u but "
+ "its waitforcapacity task is for map object %u! Removing from "
+ "queue.\n",
+ worker.serial(),
+ serial(),
+ state->objvar1.serial());
+ else {
+ ++r;
+ continue;
+ }
+ r = wl_erase(queue, r.current);
+ }
}
/**
* Create a flag at the given location
*/
-Flag::Flag
- (Editor_Game_Base & egbase, Player & owning_player, Coords const coords)
- :
- PlayerImmovable (g_flag_descr),
- m_building (0),
- m_item_capacity (8),
- m_item_filled (0),
- m_items (new PendingItem[m_item_capacity]),
- m_always_call_for_flag(0)
-{
- for (uint32_t i = 0; i < 6; ++i) m_roads[i] = 0;
-
- set_owner(&owning_player);
-
- set_flag_position(coords);
-
-
- upcast(Road, road, egbase.map().get_immovable(coords));
- upcast(Game, game, &egbase);
-
- if (game) {
- // we split a road, or a new, standalone flag is created
- (road ? road->get_economy() : new Economy (owning_player))
- ->add_flag(*this);
-
- if (road)
- road->presplit(*game, coords);
- }
-
- init(egbase);
-
- if (road and game)
- road->postsplit(*game, *this);
-}
-
-void Flag::set_flag_position(Coords coords) {
- m_position = coords;
-}
-
-int32_t Flag::get_type() const throw ()
-{
- return FLAG;
-}
-
-int32_t Flag::get_size() const throw ()
-{
- return SMALL;
-}
-
-bool Flag::get_passable() const throw ()
-{
- return true;
-}
-
+Flag::Flag(Editor_Game_Base& egbase, Player& owning_player, Coords const coords)
+ : PlayerImmovable(g_flag_descr),
+ m_building(0),
+ m_item_capacity(8),
+ m_item_filled(0),
+ m_items(new PendingItem[m_item_capacity]),
+ m_always_call_for_flag(0) {
+ for (uint32_t i = 0; i < 6; ++i)
+ m_roads[i] = 0;
+
+ set_owner(&owning_player);
+
+ set_flag_position(coords);
+
+ upcast(Road, road, egbase.map().get_immovable(coords));
+ upcast(Game, game, &egbase);
+
+ if (game) {
+ // we split a road, or a new, standalone flag is created
+ (road ? road->get_economy() : new Economy(owning_player))->add_flag(*this);
+
+ if (road)
+ road->presplit(*game, coords);
+ }
+
+ init(egbase);
+
+ if (road and game)
+ road->postsplit(*game, *this);
+}
+
+void Flag::set_flag_position(Coords coords) { m_position = coords; }
+
+int32_t Flag::get_type() const throw() { return FLAG; }
+
+int32_t Flag::get_size() const throw() { return SMALL; }
+
+bool Flag::get_passable() const throw() { return true; }
static std::string const flag_name = "flag";
-const std::string & Flag::name() const throw () {return flag_name;}
-
-
-Flag & Flag::base_flag()
-{
- return *this;
-}
+const std::string& Flag::name() const throw() { return flag_name; }
+
+Flag& Flag::base_flag() { return *this; }
/**
* Call this only from Economy code!
*/
-void Flag::set_economy(Economy * const e)
-{
- Economy * const old = get_economy();
-
- if (old == e)
- return;
-
- PlayerImmovable::set_economy(e);
-
- for (int32_t i = 0; i < m_item_filled; ++i)
- m_items[i].item->set_economy(e);
-
- if (m_building)
- m_building->set_economy(e);
-
- container_iterate_const(FlagJobs, m_flag_jobs, i)
- i.current->request->set_economy(e);
-
- for (int8_t i = 0; i < 6; ++i) {
- if (m_roads[i])
- m_roads[i]->set_economy(e);
- }
+void Flag::set_economy(Economy* const e) {
+ Economy* const old = get_economy();
+
+ if (old == e)
+ return;
+
+ PlayerImmovable::set_economy(e);
+
+ for (int32_t i = 0; i < m_item_filled; ++i)
+ m_items[i].item->set_economy(e);
+
+ if (m_building)
+ m_building->set_economy(e);
+
+ container_iterate_const(FlagJobs, m_flag_jobs, i)
+ i.current->request->set_economy(e);
+
+ for (int8_t i = 0; i < 6; ++i) {
+ if (m_roads[i])
+ m_roads[i]->set_economy(e);
+ }
}
/**
* Call this only from the Building init!
*/
-void Flag::attach_building(Editor_Game_Base & egbase, Building & building)
-{
- assert(!m_building || m_building == &building);
-
- m_building = &building;
-
- const Map & map = egbase.map();
- egbase.set_road
- (map.get_fcoords(map.tl_n(m_position)), Road_SouthEast, Road_Normal);
-
- building.set_economy(get_economy());
+void Flag::attach_building(Editor_Game_Base& egbase, Building& building) {
+ assert(!m_building || m_building == &building);
+
+ m_building = &building;
+
+ const Map& map = egbase.map();
+ egbase.set_road(map.get_fcoords(map.tl_n(m_position)), Road_SouthEast, Road_Normal);
+
+ building.set_economy(get_economy());
}
/**
* Call this only from the Building cleanup!
*/
-void Flag::detach_building(Editor_Game_Base & egbase)
-{
- assert(m_building);
-
- m_building->set_economy(0);
-
- const Map & map = egbase.map();
- egbase.set_road
- (map.get_fcoords(map.tl_n(m_position)), Road_SouthEast, Road_None);
-
- m_building = 0;
-}
-
-/**
- * Call this only from the Road init!
-*/
-void Flag::attach_road(int32_t const dir, Road * const road)
-{
- assert(!m_roads[dir - 1] || m_roads[dir - 1] == road);
-
- m_roads[dir - 1] = road;
- m_roads[dir - 1]->set_economy(get_economy());
-}
-
-/**
- * Call this only from the Road init!
-*/
-void Flag::detach_road(int32_t const dir)
-{
- assert(m_roads[dir - 1]);
-
- m_roads[dir - 1]->set_economy(0);
- m_roads[dir - 1] = 0;
+void Flag::detach_building(Editor_Game_Base& egbase) {
+ assert(m_building);
+
+ m_building->set_economy(0);
+
+ const Map& map = egbase.map();
+ egbase.set_road(map.get_fcoords(map.tl_n(m_position)), Road_SouthEast, Road_None);
+
+ m_building = 0;
+}
+
+/**
+ * Call this only from the Road init!
+*/
+void Flag::attach_road(int32_t const dir, Road* const road) {
+ assert(!m_roads[dir - 1] || m_roads[dir - 1] == road);
+
+ m_roads[dir - 1] = road;
+ m_roads[dir - 1]->set_economy(get_economy());
+}
+
+/**
+ * Call this only from the Road init!
+*/
+void Flag::detach_road(int32_t const dir) {
+ assert(m_roads[dir - 1]);
+
+ m_roads[dir - 1]->set_economy(0);
+ m_roads[dir - 1] = 0;
}
/**
* Return all positions we occupy on the map. For a Flag, this is only one
*/
-BaseImmovable::PositionList Flag::get_positions
- (const Editor_Game_Base &) const throw ()
-{
- PositionList rv;
- rv.push_back(m_position);
- return rv;
+BaseImmovable::PositionList Flag::get_positions(const Editor_Game_Base&) const throw() {
+ PositionList rv;
+ rv.push_back(m_position);
+ return rv;
}
/**
* Return neighbouring flags.
*/
-void Flag::get_neighbours(WareWorker type, RoutingNodeNeighbours & neighbours)
-{
- for (int8_t i = 0; i < 6; ++i) {
- Road * const road = m_roads[i];
- if (!road)
- continue;
-
- Flag * f = &road->get_flag(Road::FlagEnd);
- int32_t nb_cost;
- if (f != this) {
- nb_cost = road->get_cost(Road::FlagStart);
- } else {
- f = &road->get_flag(Road::FlagStart);
- nb_cost = road->get_cost(Road::FlagEnd);
- }
- if (type == wwWARE) {
- nb_cost += nb_cost * (get_waitcost() + f->get_waitcost()) / 2;
- }
- RoutingNodeNeighbour n(f, nb_cost);
-
- assert(n.get_neighbour() != this);
- neighbours.push_back(n);
- }
-
- if (m_building && m_building->descr().get_isport()) {
- Warehouse * wh = static_cast<Warehouse *>(m_building);
- if (PortDock * pd = wh->get_portdock()) {
- pd->add_neighbours(neighbours);
- }
- }
+void Flag::get_neighbours(WareWorker type, RoutingNodeNeighbours& neighbours) {
+ for (int8_t i = 0; i < 6; ++i) {
+ Road* const road = m_roads[i];
+ if (!road)
+ continue;
+
+ Flag* f = &road->get_flag(Road::FlagEnd);
+ int32_t nb_cost;
+ if (f != this) {
+ nb_cost = road->get_cost(Road::FlagStart);
+ } else {
+ f = &road->get_flag(Road::FlagStart);
+ nb_cost = road->get_cost(Road::FlagEnd);
+ }
+ if (type == wwWARE) {
+ nb_cost += nb_cost * (get_waitcost() + f->get_waitcost()) / 2;
+ }
+ RoutingNodeNeighbour n(f, nb_cost);
+
+ assert(n.get_neighbour() != this);
+ neighbours.push_back(n);
+ }
+
+ if (m_building && m_building->descr().get_isport()) {
+ Warehouse* wh = static_cast<Warehouse*>(m_building);
+ if (PortDock* pd = wh->get_portdock()) {
+ pd->add_neighbours(neighbours);
+ }
+ }
}
/**
* Return the road that leads to the given flag.
*/
-Road * Flag::get_road(Flag & flag)
-{
- for (int8_t i = 0; i < 6; ++i)
- if (Road * const road = m_roads[i])
- if
- (&road->get_flag(Road::FlagStart) == &flag ||
- &road->get_flag(Road::FlagEnd) == &flag)
- return road;
+Road* Flag::get_road(Flag& flag) {
+ for (int8_t i = 0; i < 6; ++i)
+ if (Road* const road = m_roads[i])
+ if (&road->get_flag(Road::FlagStart) == &flag || &road->get_flag(Road::FlagEnd) == &flag)
+ return road;
- return 0;
+ return 0;
}
-
/// returns the number of roads connected to the flag
uint8_t Flag::nr_of_roads() const {
- uint8_t counter = 0;
- for (uint8_t road_id = 6; road_id; --road_id)
- if (get_road(road_id) != NULL)
- ++counter;
- return counter;
+ uint8_t counter = 0;
+ for (uint8_t road_id = 6; road_id; --road_id)
+ if (get_road(road_id) != NULL)
+ ++counter;
+ return counter;
}
-
bool Flag::is_dead_end() const {
- if (get_building())
- return false;
- Flag const * first_other_flag = 0;
- for (uint8_t road_id = 6; road_id; --road_id)
- if (Road * const road = get_road(road_id)) {
- Flag & start = road->get_flag(Road::FlagStart);
- Flag & other = this == &start ? road->get_flag(Road::FlagEnd) : start;
- if (first_other_flag) {
- if (&other != first_other_flag)
- return false;
- } else
- first_other_flag = &other;
- }
- return true;
+ if (get_building())
+ return false;
+ Flag const* first_other_flag = 0;
+ for (uint8_t road_id = 6; road_id; --road_id)
+ if (Road* const road = get_road(road_id)) {
+ Flag& start = road->get_flag(Road::FlagStart);
+ Flag& other = this == &start ? road->get_flag(Road::FlagEnd) : start;
+ if (first_other_flag) {
+ if (&other != first_other_flag)
+ return false;
+ } else
+ first_other_flag = &other;
+ }
+ return true;
}
-
/**
* Returns true if the flag can hold more items.
*/
-bool Flag::has_capacity() const
-{
- return (m_item_filled < m_item_capacity);
-}
+bool Flag::has_capacity() const { return (m_item_filled < m_item_capacity); }
/**
* Signal the given bob by interrupting its task as soon as capacity becomes
@@ -356,51 +315,45 @@
*
* The capacity queue is a simple FIFO queue.
*/
-void Flag::wait_for_capacity(Game &, Worker & bob)
-{
- m_capacity_wait.push_back(&bob);
-}
+void Flag::wait_for_capacity(Game&, Worker& bob) { m_capacity_wait.push_back(&bob); }
/**
* Remove the worker from the list of workers waiting for free capacity.
*/
-void Flag::skip_wait_for_capacity(Game &, Worker & w)
-{
- CapacityWaitQueue::iterator const it =
- std::find(m_capacity_wait.begin(), m_capacity_wait.end(), &w);
- if (it != m_capacity_wait.end())
- m_capacity_wait.erase(it);
+void Flag::skip_wait_for_capacity(Game&, Worker& w) {
+ CapacityWaitQueue::iterator const it =
+ std::find(m_capacity_wait.begin(), m_capacity_wait.end(), &w);
+ if (it != m_capacity_wait.end())
+ m_capacity_wait.erase(it);
}
-
-void Flag::add_item(Editor_Game_Base & egbase, WareInstance & item)
-{
-
- assert(m_item_filled < m_item_capacity);
-
- PendingItem & pi = m_items[m_item_filled++];
- pi.item = &item;
- pi.pending = false;
- pi.nextstep = 0;
- pi.priority = 0;
-
- Transfer * trans = item.get_transfer();
- if (trans) {
- uint32_t trans_steps = trans->get_steps_left();
- if (trans_steps < 3)
- pi.priority = 2;
- else if (trans_steps == 3)
- pi.priority = 1;
-
- Request * req = trans->get_request();
- if (req)
- pi.priority = pi.priority + req->get_transfer_priority();
- }
-
- item.set_location(egbase, this);
-
- if (upcast(Game, game, &egbase))
- item.update(*game); // will call call_carrier() if necessary
+void Flag::add_item(Editor_Game_Base& egbase, WareInstance& item) {
+
+ assert(m_item_filled < m_item_capacity);
+
+ PendingItem& pi = m_items[m_item_filled++];
+ pi.item = &item;
+ pi.pending = false;
+ pi.nextstep = 0;
+ pi.priority = 0;
+
+ Transfer* trans = item.get_transfer();
+ if (trans) {
+ uint32_t trans_steps = trans->get_steps_left();
+ if (trans_steps < 3)
+ pi.priority = 2;
+ else if (trans_steps == 3)
+ pi.priority = 1;
+
+ Request* req = trans->get_request();
+ if (req)
+ pi.priority = pi.priority + req->get_transfer_priority();
+ }
+
+ item.set_location(egbase, this);
+
+ if (upcast(Game, game, &egbase))
+ item.update(*game); // will call call_carrier() if necessary
}
/**
@@ -409,59 +362,58 @@
* \note Due to fetch_from_flag() semantics, this function makes no sense
* for a building destination.
*/
-bool Flag::has_pending_item(Game &, Flag & dest) {
- for (int32_t i = 0; i < m_item_filled; ++i) {
- if (!m_items[i].pending)
- continue;
-
- if (m_items[i].nextstep != &dest)
- continue;
-
- return true;
- }
-
- return false;
+bool Flag::has_pending_item(Game&, Flag& dest) {
+ for (int32_t i = 0; i < m_item_filled; ++i) {
+ if (!m_items[i].pending)
+ continue;
+
+ if (m_items[i].nextstep != &dest)
+ continue;
+
+ return true;
+ }
+
+ return false;
}
/**
* Clamp the maximal value of \ref PendingItem::priority.
* After reaching this value, the pure FIFO approach is applied
*/
-#define MAX_TRANSFER_PRIORITY 16
-
+#define MAX_TRANSFER_PRIORITY 16
/**
* Called by carrier code to indicate that the carrier is moving to pick up an
* item. Item with highest transfer priority is chosen.
* \return true if an item is actually waiting for the carrier.
*/
-bool Flag::ack_pickup(Game &, Flag & destflag) {
- int32_t highest_pri = -1;
- int32_t i_pri = -1;
-
- for (int32_t i = 0; i < m_item_filled; ++i) {
- if (!m_items[i].pending)
- continue;
-
- if (m_items[i].nextstep != &destflag)
- continue;
-
- if (m_items[i].priority > highest_pri) {
- highest_pri = m_items[i].priority;
- i_pri = i;
-
- // Increase item priority, it matters only if the ware has to wait.
- if (m_items[i].priority < MAX_TRANSFER_PRIORITY)
- m_items[i].priority++;
- }
- }
-
- if (i_pri >= 0) {
- m_items[i_pri].pending = false;
- return true;
- }
-
- return false;
+bool Flag::ack_pickup(Game&, Flag& destflag) {
+ int32_t highest_pri = -1;
+ int32_t i_pri = -1;
+
+ for (int32_t i = 0; i < m_item_filled; ++i) {
+ if (!m_items[i].pending)
+ continue;
+
+ if (m_items[i].nextstep != &destflag)
+ continue;
+
+ if (m_items[i].priority > highest_pri) {
+ highest_pri = m_items[i].priority;
+ i_pri = i;
+
+ // Increase item priority, it matters only if the ware has to wait.
+ if (m_items[i].priority < MAX_TRANSFER_PRIORITY)
+ m_items[i].priority++;
+ }
+ }
+
+ if (i_pri >= 0) {
+ m_items[i_pri].pending = false;
+ return true;
+ }
+
+ return false;
}
/**
* Called by the carriercode when the carrier is called away from his job
@@ -469,43 +421,42 @@
* to be picked by another carrier. Returns true if an item was indeed
* made pending again
*/
-bool Flag::cancel_pickup(Game & game, Flag & destflag) {
- int32_t lowest_prio = MAX_TRANSFER_PRIORITY + 1;
- int32_t i_pri = -1;
-
- for (int32_t i = 0; i < m_item_filled; ++i) {
- if (m_items[i].pending)
- continue;
-
- if (m_items[i].nextstep != &destflag)
- continue;
-
- if (m_items[i].priority < lowest_prio) {
- lowest_prio = m_items[i].priority;
- i_pri = i;
- }
- }
-
- if (i_pri >= 0) {
- m_items[i_pri].pending = true;
- m_items[i_pri].item->update(game); // will call call_carrier() if necessary
- return true;
- }
-
- return false;
+bool Flag::cancel_pickup(Game& game, Flag& destflag) {
+ int32_t lowest_prio = MAX_TRANSFER_PRIORITY + 1;
+ int32_t i_pri = -1;
+
+ for (int32_t i = 0; i < m_item_filled; ++i) {
+ if (m_items[i].pending)
+ continue;
+
+ if (m_items[i].nextstep != &destflag)
+ continue;
+
+ if (m_items[i].priority < lowest_prio) {
+ lowest_prio = m_items[i].priority;
+ i_pri = i;
+ }
+ }
+
+ if (i_pri >= 0) {
+ m_items[i_pri].pending = true;
+ m_items[i_pri].item->update(game); // will call call_carrier() if necessary
+ return true;
+ }
+
+ return false;
}
/**
* Wake one sleeper from the capacity queue.
*/
-void Flag::wake_up_capacity_queue(Game & game)
-{
- while (!m_capacity_wait.empty()) {
- Worker * const w = m_capacity_wait[0].get(game);
- m_capacity_wait.erase(m_capacity_wait.begin());
- if (w and w->wakeup_flag_capacity(game, *this))
- break;
- }
+void Flag::wake_up_capacity_queue(Game& game) {
+ while (!m_capacity_wait.empty()) {
+ Worker* const w = m_capacity_wait[0].get(game);
+ m_capacity_wait.erase(m_capacity_wait.begin());
+ if (w and w->wakeup_flag_capacity(game, *this))
+ break;
+ }
}
/**
@@ -515,35 +466,34 @@
* This function may return 0 even if \ref ack_pickup() has already been
* called successfully.
*/
-WareInstance * Flag::fetch_pending_item(Game & game, PlayerImmovable & dest)
-{
- int32_t best_index = -1;
-
- for (int32_t i = 0; i < m_item_filled; ++i) {
- if (m_items[i].nextstep != &dest)
- continue;
-
- // We prefer to retrieve items that have already been acked
- if (best_index < 0 || !m_items[i].pending)
- best_index = i;
- }
-
- if (best_index < 0)
- return 0;
-
- // move the other items up the list and return this one
- WareInstance * const item = m_items[best_index].item;
- --m_item_filled;
- memmove
- (&m_items[best_index], &m_items[best_index + 1],
- sizeof(m_items[0]) * (m_item_filled - best_index));
-
- item->set_location(game, 0);
-
- // wake up capacity wait queue
- wake_up_capacity_queue(game);
-
- return item;
+WareInstance* Flag::fetch_pending_item(Game& game, PlayerImmovable& dest) {
+ int32_t best_index = -1;
+
+ for (int32_t i = 0; i < m_item_filled; ++i) {
+ if (m_items[i].nextstep != &dest)
+ continue;
+
+ // We prefer to retrieve items that have already been acked
+ if (best_index < 0 || !m_items[i].pending)
+ best_index = i;
+ }
+
+ if (best_index < 0)
+ return 0;
+
+ // move the other items up the list and return this one
+ WareInstance* const item = m_items[best_index].item;
+ --m_item_filled;
+ memmove(&m_items[best_index],
+ &m_items[best_index + 1],
+ sizeof(m_items[0]) * (m_item_filled - best_index));
+
+ item->set_location(game, 0);
+
+ // wake up capacity wait queue
+ wake_up_capacity_queue(game);
+
+ return item;
}
/**
@@ -551,38 +501,33 @@
* the result value to stay valid and do not change them
*/
Flag::Wares Flag::get_items() {
- Wares rv;
-
- for (int32_t i = 0; i < m_item_filled; ++i)
- rv.push_back(m_items[i].item);
-
- return rv;
+ Wares rv;
+
+ for (int32_t i = 0; i < m_item_filled; ++i)
+ rv.push_back(m_items[i].item);
+
+ return rv;
}
/**
* Force a removal of the given item from this flag.
* Called by \ref WareInstance::cleanup()
*/
-void Flag::remove_item(Editor_Game_Base & egbase, WareInstance * const item)
-{
- for (int32_t i = 0; i < m_item_filled; ++i) {
- if (m_items[i].item != item)
- continue;
-
- --m_item_filled;
- memmove
- (&m_items[i], &m_items[i + 1],
- sizeof(m_items[0]) * (m_item_filled - i));
-
- if (upcast(Game, game, &egbase))
- wake_up_capacity_queue(*game);
-
- return;
- }
-
- throw wexception
- ("MO(%u): Flag::remove_item: item %u not on flag",
- serial(), item->serial());
+void Flag::remove_item(Editor_Game_Base& egbase, WareInstance* const item) {
+ for (int32_t i = 0; i < m_item_filled; ++i) {
+ if (m_items[i].item != item)
+ continue;
+
+ --m_item_filled;
+ memmove(&m_items[i], &m_items[i + 1], sizeof(m_items[0]) * (m_item_filled - i));
+
+ if (upcast(Game, game, &egbase))
+ wake_up_capacity_queue(*game);
+
+ return;
+ }
+
+ throw wexception("MO(%u): Flag::remove_item: item %u not on flag", serial(), item->serial());
}
/**
@@ -599,84 +544,80 @@
* update_items() to ensure that new carriers are called when roads are
* split, for example.
*/
-void Flag::call_carrier
- (Game & game, WareInstance & item, PlayerImmovable * const nextstep)
-{
- PendingItem * pi = 0;
- int32_t i = 0;
-
- // Find the PendingItem entry
- for (; i < m_item_filled; ++i) {
- if (m_items[i].item != &item)
- continue;
-
- pi = &m_items[i];
- break;
- }
-
- assert(pi);
-
- // Deal with the non-moving case quickly
- if (!nextstep) {
- pi->nextstep = 0;
- pi->pending = true;
- return;
- }
-
- // Find out whether we need to do anything
- if (pi->nextstep == nextstep && pi->nextstep != m_always_call_for_flag)
- return; // no update needed
-
- pi->nextstep = nextstep;
- pi->pending = false;
-
- // Deal with the building case
- if (nextstep == get_building()) {
- molog
- ("Flag::call_carrier(%u): Tell building to fetch this item\n",
- item.serial());
-
- if (!get_building()->fetch_from_flag(game)) {
- pi->item->cancel_moving();
- pi->item->update(game);
- }
-
- return;
- }
-
- // Deal with the normal (flag) case
- ref_cast<Flag const, PlayerImmovable const>(*nextstep);
-
- for (int32_t dir = 1; dir <= 6; ++dir) {
- Road * const road = get_road(dir);
- Flag * other;
- Road::FlagId flagid;
-
- if (!road)
- continue;
-
- if (&road->get_flag(Road::FlagStart) == this) {
- flagid = Road::FlagStart;
- other = &road->get_flag(Road::FlagEnd);
- } else {
- flagid = Road::FlagEnd;
- other = &road->get_flag(Road::FlagStart);
- }
-
- if (other != nextstep)
- continue;
-
- // Yes, this is the road we want; inform it
- if (road->notify_ware(game, flagid))
- return;
-
- // If the road doesn't react to the ware immediately, we try other roads:
- // They might lead to the same flag!
- }
-
- // Nothing found, just let it be picked up by somebody
- pi->pending = true;
- return;
+void Flag::call_carrier(Game& game, WareInstance& item, PlayerImmovable* const nextstep) {
+ PendingItem* pi = 0;
+ int32_t i = 0;
+
+ // Find the PendingItem entry
+ for (; i < m_item_filled; ++i) {
+ if (m_items[i].item != &item)
+ continue;
+
+ pi = &m_items[i];
+ break;
+ }
+
+ assert(pi);
+
+ // Deal with the non-moving case quickly
+ if (!nextstep) {
+ pi->nextstep = 0;
+ pi->pending = true;
+ return;
+ }
+
+ // Find out whether we need to do anything
+ if (pi->nextstep == nextstep && pi->nextstep != m_always_call_for_flag)
+ return; // no update needed
+
+ pi->nextstep = nextstep;
+ pi->pending = false;
+
+ // Deal with the building case
+ if (nextstep == get_building()) {
+ molog("Flag::call_carrier(%u): Tell building to fetch this item\n", item.serial());
+
+ if (!get_building()->fetch_from_flag(game)) {
+ pi->item->cancel_moving();
+ pi->item->update(game);
+ }
+
+ return;
+ }
+
+ // Deal with the normal (flag) case
+ ref_cast<Flag const, PlayerImmovable const>(*nextstep);
+
+ for (int32_t dir = 1; dir <= 6; ++dir) {
+ Road* const road = get_road(dir);
+ Flag* other;
+ Road::FlagId flagid;
+
+ if (!road)
+ continue;
+
+ if (&road->get_flag(Road::FlagStart) == this) {
+ flagid = Road::FlagStart;
+ other = &road->get_flag(Road::FlagEnd);
+ } else {
+ flagid = Road::FlagEnd;
+ other = &road->get_flag(Road::FlagStart);
+ }
+
+ if (other != nextstep)
+ continue;
+
+ // Yes, this is the road we want; inform it
+ if (road->notify_ware(game, flagid))
+ return;
+
+ // If the road doesn't react to the ware immediately, we try other roads:
+ // They might lead to the same flag!
+ }
+
+ // Nothing found, just let it be picked up by somebody
+ pi->pending = true;
+ return;
}
/**
@@ -689,66 +630,63 @@
* fragile.
* A similar thing can happen when a road is split.
*/
-void Flag::update_items(Game & game, Flag * const other)
-{
- m_always_call_for_flag = other;
-
- for (int32_t i = 0; i < m_item_filled; ++i)
- m_items[i].item->update(game);
-
- m_always_call_for_flag = 0;
+void Flag::update_items(Game& game, Flag* const other) {
+ m_always_call_for_flag = other;
+
+ for (int32_t i = 0; i < m_item_filled; ++i)
+ m_items[i].item->update(game);
+
+ m_always_call_for_flag = 0;
}
-void Flag::init(Editor_Game_Base & egbase)
-{
- PlayerImmovable::init(egbase);
-
- set_position(egbase, m_position);
-
- m_animstart = egbase.get_gametime();
+void Flag::init(Editor_Game_Base& egbase) {
+ PlayerImmovable::init(egbase);
+
+ set_position(egbase, m_position);
+
+ m_animstart = egbase.get_gametime();
}
/**
* Detach building and free roads.
*/
-void Flag::cleanup(Editor_Game_Base & egbase)
-{
- //molog("Flag::cleanup\n");
-
- while (!m_flag_jobs.empty()) {
- delete m_flag_jobs.begin()->request;
- m_flag_jobs.erase(m_flag_jobs.begin());
- }
-
- while (m_item_filled) {
- WareInstance & item = *m_items[--m_item_filled].item;
-
- item.set_location(egbase, 0);
- item.destroy (egbase);
- }
-
- //molog(" items destroyed\n");
-
- if (m_building) {
- m_building->remove(egbase); // immediate death
- assert(!m_building);
- }
-
- for (int8_t i = 0; i < 6; ++i) {
- if (m_roads[i]) {
- m_roads[i]->remove(egbase); // immediate death
- assert(!m_roads[i]);
- }
- }
-
- if (Economy * e = get_economy())
- e->remove_flag(*this);
-
- unset_position(egbase, m_position);
-
- //molog(" done\n");
-
- PlayerImmovable::cleanup(egbase);
+void Flag::cleanup(Editor_Game_Base& egbase) {
+ //molog("Flag::cleanup\n");
+
+ while (!m_flag_jobs.empty()) {
+ delete m_flag_jobs.begin()->request;
+ m_flag_jobs.erase(m_flag_jobs.begin());
+ }
+
+ while (m_item_filled) {
+ WareInstance& item = *m_items[--m_item_filled].item;
+
+ item.set_location(egbase, 0);
+ item.destroy(egbase);
+ }
+
+ //molog(" items destroyed\n");
+
+ if (m_building) {
+ m_building->remove(egbase); // immediate death
+ assert(!m_building);
+ }
+
+ for (int8_t i = 0; i < 6; ++i) {
+ if (m_roads[i]) {
+ m_roads[i]->remove(egbase); // immediate death
+ assert(!m_roads[i]);
+ }
+ }
+
+ if (Economy* e = get_economy())
+ e->remove_flag(*this);
+
+ unset_position(egbase, m_position);
+
+ //molog(" done\n");
+
+ PlayerImmovable::cleanup(egbase);
}
/**
@@ -758,82 +696,74 @@
* \ref Flag::cleanup(). This function is needed to ensure a fire is created
* when a player removes a flag.
*/
-void Flag::destroy(Editor_Game_Base & egbase)
-{
- if (m_building) {
- m_building->destroy(egbase);
- assert(!m_building);
- }
+void Flag::destroy(Editor_Game_Base& egbase) {
+ if (m_building) {
+ m_building->destroy(egbase);
+ assert(!m_building);
+ }
- PlayerImmovable::destroy(egbase);
+ PlayerImmovable::destroy(egbase);
}
/**
* Add a new flag job to request the worker with the given ID, and to execute
* the given program once it's completed.
*/
-void Flag::add_flag_job
- (Game &, Ware_Index const workerware, const std::string & programname)
-{
- FlagJob j;
-
- j.request =
- new Request
- (*this, workerware, Flag::flag_job_request_callback, wwWORKER);
- j.program = programname;
-
- m_flag_jobs.push_back(j);
+void Flag::add_flag_job(Game&, Ware_Index const workerware, const std::string& programname) {
+ FlagJob j;
+
+ j.request = new Request(*this, workerware, Flag::flag_job_request_callback, wwWORKER);
+ j.program = programname;
+
+ m_flag_jobs.push_back(j);
}
/**
* This function is called when one of the flag job workers arrives on
* the flag. Give him his job.
*/
-void Flag::flag_job_request_callback
- (Game & game,
- Request & rq,
- Ware_Index,
- Worker * const w,
- PlayerImmovable & target)
-{
- Flag & flag = ref_cast<Flag, PlayerImmovable>(target);
-
- assert(w);
-
- container_iterate(FlagJobs, flag.m_flag_jobs, i)
- if (i.current->request == &rq) {
- delete &rq;
-
- w->start_task_program(game, i.current->program);
-
- flag.m_flag_jobs.erase(i.current);
- return;
- }
-
- flag.molog("BUG: flag_job_request_callback: worker not found in list\n");
-}
-
-void Flag::log_general_info(const Widelands::Editor_Game_Base & egbase)
-{
- molog("Flag at %i,%i\n", m_position.x, m_position.y);
-
- Widelands::PlayerImmovable::log_general_info(egbase);
-
- if (m_item_filled) {
- molog("Wares at flag:\n");
- for (int i = 0; i < m_item_filled; ++i) {
- PendingItem & pi = m_items[i];
- molog
- (" %i/%i: %s(%i), nextstep %i, %s\n",
- i + 1, m_item_capacity,
- pi.item->descr().name().c_str(), pi.item->serial(),
- pi.nextstep.serial(),
- pi.pending ? "pending" : "acked by carrier");
- }
- } else {
- molog("No wares at flag.\n");
- }
-}
-
+void Flag::flag_job_request_callback(Game& game,
+ Request& rq,
+ Ware_Index,
+ Worker* const w,
+ PlayerImmovable& target) {
+ Flag& flag = ref_cast<Flag, PlayerImmovable>(target);
+
+ assert(w);
+
+ container_iterate(FlagJobs, flag.m_flag_jobs, i)
+ if (i.current->request == &rq) {
+ delete &rq;
+
+ w->start_task_program(game, i.current->program);
+
+ flag.m_flag_jobs.erase(i.current);
+ return;
+ }
+
+ flag.molog("BUG: flag_job_request_callback: worker not found in list\n");
+}
+
+void Flag::log_general_info(const Widelands::Editor_Game_Base& egbase) {
+ molog("Flag at %i,%i\n", m_position.x, m_position.y);
+
+ Widelands::PlayerImmovable::log_general_info(egbase);
+
+ if (m_item_filled) {
+ molog("Wares at flag:\n");
+ for (int i = 0; i < m_item_filled; ++i) {
+ PendingItem& pi = m_items[i];
+ molog(" %i/%i: %s(%i), nextstep %i, %s\n",
+ i + 1,
+ m_item_capacity,
+ pi.item->descr().name().c_str(),
+ pi.item->serial(),
+ pi.nextstep.serial(),
+ pi.pending ? "pending" : "acked by carrier");
+ }
+ } else {
+ molog("No wares at flag.\n");
+ }
+}
}
=== modified file 'src/economy/flag.h'
--- src/economy/flag.h 2013-04-22 20:15:00 +0000
+++ src/economy/flag.h 2013-05-18 05:56:27 +0000
@@ -32,8 +32,6 @@
struct Road;
class WareInstance;
-
-
/**
* Flag represents a flag, obviously.
* A flag itself doesn't do much. However, it can have up to 6 roads attached
@@ -50,120 +48,118 @@
* WALK_xx in all "direction" parameters.
*/
struct Flag : public PlayerImmovable, public RoutingNode {
- typedef std::vector<const WareInstance *> Wares;
-
- friend class Economy;
- friend struct Router;
- friend class FlagQueue;
- friend struct Map_Ware_Data_Packet; // has to look at pending items
- friend struct Map_Waredata_Data_Packet; // has to look at pending items
- friend struct Map_Flagdata_Data_Packet; // has to read/write this to a file
-
- Flag(); /// empty flag for savegame loading
- Flag(Editor_Game_Base &, Player & owner, Coords); /// create a new flag
- virtual ~Flag();
-
- void load_finish(Editor_Game_Base &);
- virtual void destroy(Editor_Game_Base &);
-
- virtual int32_t get_type () const throw ();
- char const * type_name() const throw () {return "flag";}
- virtual int32_t get_size () const throw ();
- virtual bool get_passable() const throw ();
- const std::string & name() const throw ();
-
- virtual Flag & base_flag();
-
- const Coords & get_position() const {return m_position;}
- virtual PositionList get_positions (const Editor_Game_Base &) const throw ();
- void get_neighbours(WareWorker type, RoutingNodeNeighbours &);
- int32_t get_waitcost() const {return m_item_filled;}
-
- virtual void set_economy(Economy *);
-
- Building * get_building() const {return m_building;}
- void attach_building(Editor_Game_Base &, Building &);
- void detach_building(Editor_Game_Base &);
-
- bool has_road() const {
- return
- m_roads[0] or m_roads[1] or m_roads[2] or
- m_roads[3] or m_roads[4] or m_roads[5];
- }
- Road * get_road(uint8_t const dir) const {return m_roads[dir - 1];}
- uint8_t nr_of_roads() const;
- void attach_road(int32_t dir, Road *);
- void detach_road(int32_t dir);
-
- Road * get_road(Flag &);
-
- bool is_dead_end() const;
-
- bool has_capacity() const;
- uint32_t total_capacity() {return m_item_capacity;}
- uint32_t current_items() const {return m_item_filled;}
- void wait_for_capacity(Game &, Worker &);
- void skip_wait_for_capacity(Game &, Worker &);
- void add_item(Editor_Game_Base &, WareInstance &);
- bool has_pending_item(Game &, Flag & destflag);
- bool ack_pickup(Game &, Flag & destflag);
- bool cancel_pickup(Game &, Flag & destflag);
- WareInstance * fetch_pending_item(Game &, PlayerImmovable & dest);
- Wares get_items();
-
- void call_carrier(Game &, WareInstance &, PlayerImmovable * nextstep);
- void update_items(Game &, Flag * other);
-
- void remove_item(Editor_Game_Base &, WareInstance * const);
-
- void add_flag_job(Game &, Ware_Index workerware, const std::string & programname);
-
- virtual void log_general_info(const Editor_Game_Base &);
-
-protected:
- virtual void init(Editor_Game_Base &);
- virtual void cleanup(Editor_Game_Base &);
-
- virtual void draw(const Editor_Game_Base &, RenderTarget &, FCoords, Point);
-
- void wake_up_capacity_queue(Game &);
-
- static void flag_job_request_callback(Game &, Request &, Ware_Index, Worker *, PlayerImmovable &);
-
- void set_flag_position(Coords coords);
-
-private:
- struct PendingItem {
- WareInstance * item; ///< the item itself
- bool pending; ///< if the item is pending
- int32_t priority; ///< carrier prefers the item with highest priority
- OPtr<PlayerImmovable> nextstep; ///< next step that this item is sent to
- };
-
- struct FlagJob {
- Request * request;
- std::string program;
- };
-
- Coords m_position;
- int32_t m_animstart;
-
- Building * m_building; ///< attached building (replaces road WALK_NW)
- Road * m_roads[6]; ///< WALK_xx - 1 as index
-
- int32_t m_item_capacity; ///< size of m_items array
- int32_t m_item_filled; ///< number of items currently on the flag
- PendingItem * m_items; ///< items currently on the flag
-
- /// call_carrier() will always call a carrier when the destination is
- /// the given flag
- Flag * m_always_call_for_flag;
-
- typedef std::vector<OPtr<Worker> > CapacityWaitQueue;
- CapacityWaitQueue m_capacity_wait; ///< workers waiting for capacity
-
- typedef std::list<FlagJob> FlagJobs;
- FlagJobs m_flag_jobs;
+ typedef std::vector<const WareInstance*> Wares;
+
+ friend class Economy;
+ friend struct Router;
+ friend class FlagQueue;
+ friend struct Map_Ware_Data_Packet; // has to look at pending items
+ friend struct Map_Waredata_Data_Packet; // has to look at pending items
+ friend struct Map_Flagdata_Data_Packet; // has to read/write this to a file
+
+ Flag(); /// empty flag for savegame loading
+ Flag(Editor_Game_Base&, Player& owner, Coords); /// create a new flag
+ virtual ~Flag();
+
+ void load_finish(Editor_Game_Base&);
+ virtual void destroy(Editor_Game_Base&);
+
+ virtual int32_t get_type() const throw();
+ char const* type_name() const throw() { return "flag"; }
+ virtual int32_t get_size() const throw();
+ virtual bool get_passable() const throw();
+ const std::string& name() const throw();
+
+ virtual Flag& base_flag();
+
+ const Coords& get_position() const { return m_position; }
+ virtual PositionList get_positions(const Editor_Game_Base&) const throw();
+ void get_neighbours(WareWorker type, RoutingNodeNeighbours&);
+ int32_t get_waitcost() const { return m_item_filled; }
+
+ virtual void set_economy(Economy*);
+
+ Building* get_building() const { return m_building; }
+ void attach_building(Editor_Game_Base&, Building&);
+ void detach_building(Editor_Game_Base&);
+
+ bool has_road() const {
+ return m_roads[0] or m_roads[1] or m_roads[2] or m_roads[3] or m_roads[4] or m_roads[5];
+ }
+ Road* get_road(uint8_t const dir) const { return m_roads[dir - 1]; }
+ uint8_t nr_of_roads() const;
+ void attach_road(int32_t dir, Road*);
+ void detach_road(int32_t dir);
+
+ Road* get_road(Flag&);
+
+ bool is_dead_end() const;
+
+ bool has_capacity() const;
+ uint32_t total_capacity() { return m_item_capacity; }
+ uint32_t current_items() const { return m_item_filled; }
+ void wait_for_capacity(Game&, Worker&);
+ void skip_wait_for_capacity(Game&, Worker&);
+ void add_item(Editor_Game_Base&, WareInstance&);
+ bool has_pending_item(Game&, Flag& destflag);
+ bool ack_pickup(Game&, Flag& destflag);
+ bool cancel_pickup(Game&, Flag& destflag);
+ WareInstance* fetch_pending_item(Game&, PlayerImmovable& dest);
+ Wares get_items();
+
+ void call_carrier(Game&, WareInstance&, PlayerImmovable* nextstep);
+ void update_items(Game&, Flag* other);
+
+ void remove_item(Editor_Game_Base&, WareInstance* const);
+
+ void add_flag_job(Game&, Ware_Index workerware, const std::string& programname);
+
+ virtual void log_general_info(const Editor_Game_Base&);
+
+ protected:
+ virtual void init(Editor_Game_Base&);
+ virtual void cleanup(Editor_Game_Base&);
+
+ virtual void draw(const Editor_Game_Base&, RenderTarget&, const FCoords&, const Point&);
+
+ void wake_up_capacity_queue(Game&);
+
+ static void flag_job_request_callback(Game&, Request&, Ware_Index, Worker*, PlayerImmovable&);
+
+ void set_flag_position(Coords coords);
+
+ private:
+ struct PendingItem {
+ WareInstance* item; ///< the item itself
+ bool pending; ///< if the item is pending
+ int32_t priority; ///< carrier prefers the item with highest priority
+ OPtr<PlayerImmovable> nextstep; ///< next step that this item is sent to
+ };
+
+ struct FlagJob {
+ Request* request;
+ std::string program;
+ };
+
+ Coords m_position;
+ int32_t m_animstart;
+
+ Building* m_building; ///< attached building (replaces road WALK_NW)
+ Road* m_roads[6]; ///< WALK_xx - 1 as index
+
+ int32_t m_item_capacity; ///< size of m_items array
+ int32_t m_item_filled; ///< number of items currently on the flag
+ PendingItem* m_items; ///< items currently on the flag
+
+ /// call_carrier() will always call a carrier when the destination is
+ /// the given flag
+ Flag* m_always_call_for_flag;
+
+ typedef std::vector<OPtr<Worker> > CapacityWaitQueue;
+ CapacityWaitQueue m_capacity_wait; ///< workers waiting for capacity
+
+ typedef std::list<FlagJob> FlagJobs;
+ FlagJobs m_flag_jobs;
};
}
=== modified file 'src/economy/fleet.cc'
--- src/economy/fleet.cc 2013-05-06 18:03:22 +0000
+++ src/economy/fleet.cc 2013-05-18 05:56:27 +0000
@@ -45,255 +45,235 @@
* instance, then add themselves \em before calling the \ref init function.
* The Fleet takes care of merging with existing fleets, if any.
*/
-Fleet::Fleet(Player & player) :
- Map_Object(&fleet_descr),
- m_owner(player),
- m_act_pending(false),
- m_port_roundrobin(0)
-{
-}
-
-int32_t Fleet::get_type() const throw ()
-{
- return FLEET;
-}
-
-char const * Fleet::type_name() const throw ()
-{
- return "fleet";
-}
+Fleet::Fleet(Player& player)
+ : Map_Object(&fleet_descr), m_owner(player), m_act_pending(false), m_port_roundrobin(0) {}
+
+int32_t Fleet::get_type() const throw() { return FLEET; }
+
+char const* Fleet::type_name() const throw() { return "fleet"; }
/**
* Whether the fleet is in fact useful for transporting goods.
*/
-bool Fleet::active() const
-{
- return !m_ships.empty() && m_ports.size() >= 2;
-}
+bool Fleet::active() const { return !m_ships.empty() && m_ports.size() >= 2; }
/**
* Inform the Fleet about the change of @ref Economy of one of the docks.
*
* Note that we always associate ourselves with the economy of the first dock.
*/
-void Fleet::set_economy(Economy * e)
-{
- if (!m_ships.empty()) {
- if (!m_ports.empty()) {
- e = m_ports[0]->get_economy();
- }
+void Fleet::set_economy(Economy* e) {
+ if (!m_ships.empty()) {
+ if (!m_ports.empty()) {
+ e = m_ports[0]->get_economy();
+ }
#ifndef NDEBUG
- else
- assert(e == 0);
+ else
+ assert(e == 0);
#endif
- if (upcast(Game, game, &owner().egbase())) {
- container_iterate_const(std::vector<Ship *>, m_ships, shipit) {
- (*shipit.current)->set_economy(*game, e);
- }
- }
- }
+ if (upcast(Game, game, &owner().egbase())) {
+ container_iterate_const(std::vector<Ship*>, m_ships, shipit) {
+ (*shipit.current)->set_economy(*game, e);
+ }
+ }
+ }
}
/**
* Initialize the fleet, including a search through the map
* to rejoin with the next other fleet we can find.
*/
-void Fleet::init(Editor_Game_Base & egbase)
-{
- Map_Object::init(egbase);
-
- if (m_ships.empty() && m_ports.empty()) {
- molog("Empty fleet initialized; disband immediately\n");
- remove(egbase);
- return;
- }
-
- find_other_fleet(egbase);
-
- if (active())
- update(egbase);
+void Fleet::init(Editor_Game_Base& egbase) {
+ Map_Object::init(egbase);
+
+ if (m_ships.empty() && m_ports.empty()) {
+ molog("Empty fleet initialized; disband immediately\n");
+ remove(egbase);
+ return;
+ }
+
+ find_other_fleet(egbase);
+
+ if (active())
+ update(egbase);
}
struct StepEvalFindFleet {
- int32_t estimate(Map & /* map */, FCoords /* pos */) const {return 0;}
- int32_t stepcost(Map & /* map */, FCoords from, int32_t fromcost, WalkingDir /* dir */, FCoords to) const {
- if (!(to.field->nodecaps() & (MOVECAPS_SWIM | MOVECAPS_WALK)))
- return -1;
-
- if (!(from.field->nodecaps() & MOVECAPS_SWIM)) {
- // We are allowed to land on and leave the shore,
- // but not in the middle of a path
- if (fromcost > 0)
- return -1;
-
- return 1;
- }
-
- return 1;
- }
+ int32_t estimate(Map& /* map */, FCoords /* pos */) const { return 0; }
+ int32_t stepcost(Map& /* map */,
+ FCoords from,
+ int32_t fromcost,
+ WalkingDir /* dir */,
+ FCoords to) const {
+ if (!(to.field->nodecaps() & (MOVECAPS_SWIM | MOVECAPS_WALK)))
+ return -1;
+
+ if (!(from.field->nodecaps() & MOVECAPS_SWIM)) {
+ // We are allowed to land on and leave the shore,
+ // but not in the middle of a path
+ if (fromcost > 0)
+ return -1;
+
+ return 1;
+ }
+
+ return 1;
+ }
};
/**
* Search the map, starting at our ships and ports, for another fleet
* of the same player.
*/
-void Fleet::find_other_fleet(Editor_Game_Base & egbase)
-{
- Map & map = egbase.map();
- MapAStar<StepEvalFindFleet> astar(map, StepEvalFindFleet());
-
- container_iterate_const(std::vector<Ship *>, m_ships, it) {
- astar.push((*it.current)->get_position());
- }
-
- container_iterate_const(std::vector<PortDock *>, m_ports, it) {
- BaseImmovable::PositionList pos = (*it.current)->get_positions(egbase);
-
- container_iterate_const(BaseImmovable::PositionList, pos, posit) {
- astar.push(*posit.current);
- }
- }
-
- int32_t cost;
- FCoords cur;
- while (astar.step(cur, cost)) {
- if (BaseImmovable * imm = cur.field->get_immovable()) {
- if (imm->get_type() == PORTDOCK) {
- if (upcast(PortDock, dock, imm)) {
- if (dock->get_fleet() != this && dock->get_owner() == get_owner()) {
- dock->get_fleet()->merge(egbase, this);
- return;
- }
- }
- }
- }
-
- for (Bob * bob = cur.field->get_first_bob(); bob != 0; bob = bob->get_next_bob()) {
- if (bob->get_bob_type() != Bob::SHIP)
- continue;
-
- if (upcast(Ship, ship, bob)) {
- if (ship->get_fleet() != this && ship->get_owner() == get_owner()) {
- ship->get_fleet()->merge(egbase, this);
- return;
- }
- }
- }
- }
+void Fleet::find_other_fleet(Editor_Game_Base& egbase) {
+ Map& map = egbase.map();
+ MapAStar<StepEvalFindFleet> astar(map, StepEvalFindFleet());
+
+ container_iterate_const(std::vector<Ship*>, m_ships, it) {
+ astar.push((*it.current)->get_position());
+ }
+
+ container_iterate_const(std::vector<PortDock*>, m_ports, it) {
+ BaseImmovable::PositionList pos = (*it.current)->get_positions(egbase);
+
+ container_iterate_const(BaseImmovable::PositionList, pos, posit) {
+ astar.push(*posit.current);
+ }
+ }
+
+ int32_t cost;
+ FCoords cur;
+ while (astar.step(cur, cost)) {
+ if (BaseImmovable* imm = cur.field->get_immovable()) {
+ if (imm->get_type() == PORTDOCK) {
+ if (upcast(PortDock, dock, imm)) {
+ if (dock->get_fleet() != this && dock->get_owner() == get_owner()) {
+ dock->get_fleet()->merge(egbase, this);
+ return;
+ }
+ }
+ }
+ }
+
+ for (Bob* bob = cur.field->get_first_bob(); bob != 0; bob = bob->get_next_bob()) {
+ if (bob->get_bob_type() != Bob::SHIP)
+ continue;
+
+ if (upcast(Ship, ship, bob)) {
+ if (ship->get_fleet() != this && ship->get_owner() == get_owner()) {
+ ship->get_fleet()->merge(egbase, this);
+ return;
+ }
+ }
+ }
+ }
}
/**
* Merge the @p other fleet into this fleet, and remove the other fleet.
*/
-void Fleet::merge(Editor_Game_Base & egbase, Fleet * other)
-{
- if (m_ports.empty() and not other->m_ports.empty()) {
- other->merge(egbase, this);
- return;
- }
-
- while (!other->m_ships.empty()) {
- Ship * ship = other->m_ships.back();
- other->m_ships.pop_back();
- add_ship(ship);
- }
-
- uint32_t old_nrports = m_ports.size();
- m_ports.insert(m_ports.end(), other->m_ports.begin(), other->m_ports.end());
- m_portpaths.resize((m_ports.size() * (m_ports.size() - 1)) / 2);
-
- for (uint32_t j = 1; j < other->m_ports.size(); ++j) {
- for (uint32_t i = 0; i < j; ++i) {
- portpath(old_nrports + i, old_nrports + j) = other->portpath(i, j);
- }
- }
-
- for (uint32_t idx = old_nrports; idx < m_ports.size(); ++idx) {
- m_ports[idx]->set_fleet(this);
- }
-
- if (!m_ships.empty() && !m_ports.empty())
- check_merge_economy();
-
- other->m_ports.clear();
- other->m_portpaths.clear();
- other->remove(egbase);
-
- update(egbase);
+void Fleet::merge(Editor_Game_Base& egbase, Fleet* other) {
+ if (m_ports.empty() and not other->m_ports.empty()) {
+ other->merge(egbase, this);
+ return;
+ }
+
+ while (!other->m_ships.empty()) {
+ Ship* ship = other->m_ships.back();
+ other->m_ships.pop_back();
+ add_ship(ship);
+ }
+
+ uint32_t old_nrports = m_ports.size();
+ m_ports.insert(m_ports.end(), other->m_ports.begin(), other->m_ports.end());
+ m_portpaths.resize((m_ports.size() * (m_ports.size() - 1)) / 2);
+
+ for (uint32_t j = 1; j < other->m_ports.size(); ++j) {
+ for (uint32_t i = 0; i < j; ++i) {
+ portpath(old_nrports + i, old_nrports + j) = other->portpath(i, j);
+ }
+ }
+
+ for (uint32_t idx = old_nrports; idx < m_ports.size(); ++idx) {
+ m_ports[idx]->set_fleet(this);
+ }
+
+ if (!m_ships.empty() && !m_ports.empty())
+ check_merge_economy();
+
+ other->m_ports.clear();
+ other->m_portpaths.clear();
+ other->remove(egbase);
+
+ update(egbase);
}
/**
* If we have ports and ships, ensure that all ports belong to the same economy.
*/
-void Fleet::check_merge_economy()
-{
- if (m_ports.empty() || m_ships.empty())
- return;
-
- Flag & base = m_ports[0]->base_flag();
- for (uint32_t i = 1; i < m_ports.size(); ++i) {
- // Note: economy of base flag may of course be changed by the merge!
- base.get_economy()->check_merge(base, m_ports[i]->base_flag());
- }
-}
-
-void Fleet::cleanup(Editor_Game_Base & egbase)
-{
- while (!m_ports.empty()) {
- PortDock * pd = m_ports.back();
- m_ports.pop_back();
-
- pd->set_fleet(0);
- if (!m_ports.empty() && !m_ships.empty()) {
- // This is required when, during end-of-game cleanup,
- // the fleet gets removed before the ports
- Flag & base = m_ports[0]->base_flag();
- Economy::check_split(base, pd->base_flag());
- }
- }
- m_portpaths.clear();
-
- while (!m_ships.empty()) {
- m_ships.back()->set_fleet(0);
- m_ships.pop_back();
- }
-
- Map_Object::cleanup(egbase);
-}
-
-Fleet::PortPath & Fleet::portpath(uint32_t i, uint32_t j)
-{
- assert(i < j);
-
- return m_portpaths[((j - 1) * j) / 2 + i];
-}
-
-const Fleet::PortPath & Fleet::portpath(uint32_t i, uint32_t j) const
-{
- assert(i < j);
-
- return m_portpaths[((j - 1) * j) / 2 + i];
-}
-
-Fleet::PortPath & Fleet::portpath_bidir(uint32_t i, uint32_t j, bool & reverse)
-{
- reverse = false;
- if (i > j) {
- reverse = true;
- std::swap(i, j);
- }
- return portpath(i, j);
-}
-
-const Fleet::PortPath & Fleet::portpath_bidir(uint32_t i, uint32_t j, bool & reverse) const
-{
- reverse = false;
- if (i > j) {
- reverse = true;
- std::swap(i, j);
- }
- return portpath(i, j);
+void Fleet::check_merge_economy() {
+ if (m_ports.empty() || m_ships.empty())
+ return;
+
+ Flag& base = m_ports[0]->base_flag();
+ for (uint32_t i = 1; i < m_ports.size(); ++i) {
+ // Note: economy of base flag may of course be changed by the merge!
+ base.get_economy()->check_merge(base, m_ports[i]->base_flag());
+ }
+}
+
+void Fleet::cleanup(Editor_Game_Base& egbase) {
+ while (!m_ports.empty()) {
+ PortDock* pd = m_ports.back();
+ m_ports.pop_back();
+
+ pd->set_fleet(0);
+ if (!m_ports.empty() && !m_ships.empty()) {
+ // This is required when, during end-of-game cleanup,
+ // the fleet gets removed before the ports
+ Flag& base = m_ports[0]->base_flag();
+ Economy::check_split(base, pd->base_flag());
+ }
+ }
+ m_portpaths.clear();
+
+ while (!m_ships.empty()) {
+ m_ships.back()->set_fleet(0);
+ m_ships.pop_back();
+ }
+
+ Map_Object::cleanup(egbase);
+}
+
+Fleet::PortPath& Fleet::portpath(uint32_t i, uint32_t j) {
+ assert(i < j);
+
+ return m_portpaths[((j - 1) * j) / 2 + i];
+}
+
+const Fleet::PortPath& Fleet::portpath(uint32_t i, uint32_t j) const {
+ assert(i < j);
+
+ return m_portpaths[((j - 1) * j) / 2 + i];
+}
+
+Fleet::PortPath& Fleet::portpath_bidir(uint32_t i, uint32_t j, bool& reverse) {
+ reverse = false;
+ if (i > j) {
+ reverse = true;
+ std::swap(i, j);
+ }
+ return portpath(i, j);
+}
+
+const Fleet::PortPath& Fleet::portpath_bidir(uint32_t i, uint32_t j, bool& reverse) const {
+ reverse = false;
+ if (i > j) {
+ reverse = true;
+ std::swap(i, j);
+ }
+ return portpath(i, j);
}
/**
@@ -301,122 +281,117 @@
*
* @return true if successful, or false if the docks are not actually part of the fleet.
*/
-bool Fleet::get_path(PortDock & start, PortDock & end, Path & path)
-{
- uint32_t startidx = std::find(m_ports.begin(), m_ports.end(), &start) - m_ports.begin();
- uint32_t endidx = std::find(m_ports.begin(), m_ports.end(), &end) - m_ports.begin();
-
- if (startidx >= m_ports.size() || endidx >= m_ports.size())
- return false;
-
- bool reverse;
- const PortPath & pp(portpath_bidir(startidx, endidx, reverse));
-
- if (pp.cost < 0)
- connect_port(owner().egbase(), startidx);
-
- if (pp.cost < 0)
- return false;
-
- path = *pp.path;
- if (reverse)
- path.reverse();
-
- return true;
-}
-
-void Fleet::add_neighbours(PortDock & pd, std::vector<RoutingNodeNeighbour> & neighbours)
-{
- uint32_t idx = std::find(m_ports.begin(), m_ports.end(), &pd) - m_ports.begin();
-
- for (uint32_t otheridx = 0; otheridx < m_ports.size(); ++otheridx) {
- if (idx == otheridx)
- continue;
-
- bool reverse;
- PortPath & pp(portpath_bidir(idx, otheridx, reverse));
-
- if (pp.cost < 0) {
- // Lazily discover routes between ports
- connect_port(owner().egbase(), idx);
- }
-
- if (pp.cost >= 0) {
- // TODO: keep statistics on average transport time instead of using the arbitrary 2x factor
- RoutingNodeNeighbour neighb(&m_ports[otheridx]->base_flag(), 2 * pp.cost);
- neighbours.push_back(neighb);
- }
- }
-}
-
-void Fleet::add_ship(Ship * ship)
-{
- m_ships.push_back(ship);
- ship->set_fleet(this);
- if (upcast(Game, game, &owner().egbase())) {
- if (m_ports.empty())
- ship->set_economy(*game, 0);
- else
- ship->set_economy(*game, m_ports[0]->get_economy());
- }
-
- if (m_ships.size() == 1) {
- check_merge_economy();
- }
-}
-
-void Fleet::remove_ship(Editor_Game_Base & egbase, Ship * ship)
-{
- std::vector<Ship *>::iterator it = std::find(m_ships.begin(), m_ships.end(), ship);
- if (it != m_ships.end()) {
- *it = m_ships.back();
- m_ships.pop_back();
- }
- ship->set_fleet(0);
- if (upcast(Game, game, &egbase))
- ship->set_economy(*game, 0);
-
- if (ship->get_destination(egbase))
- update(egbase);
-
- if (m_ships.empty()) {
- if (m_ports.empty()) {
- remove(egbase);
- } else {
- Flag & base = m_ports[0]->base_flag();
- for (uint32_t i = 1; i < m_ports.size(); ++i) {
- // since two ports can be connected by land, it is possible that
- // disconnecting a previous port also disconnects later ports
- if (base.get_economy() == m_ports[i]->base_flag().get_economy())
- Economy::check_split(base, m_ports[i]->base_flag());
- }
- }
- }
+bool Fleet::get_path(PortDock& start, PortDock& end, Path& path) {
+ uint32_t startidx = std::find(m_ports.begin(), m_ports.end(), &start) - m_ports.begin();
+ uint32_t endidx = std::find(m_ports.begin(), m_ports.end(), &end) - m_ports.begin();
+
+ if (startidx >= m_ports.size() || endidx >= m_ports.size())
+ return false;
+
+ bool reverse;
+ const PortPath& pp(portpath_bidir(startidx, endidx, reverse));
+
+ if (pp.cost < 0)
+ connect_port(owner().egbase(), startidx);
+
+ if (pp.cost < 0)
+ return false;
+
+ path = *pp.path;
+ if (reverse)
+ path.reverse();
+
+ return true;
+}
+
+void Fleet::add_neighbours(PortDock& pd, std::vector<RoutingNodeNeighbour>& neighbours) {
+ uint32_t idx = std::find(m_ports.begin(), m_ports.end(), &pd) - m_ports.begin();
+
+ for (uint32_t otheridx = 0; otheridx < m_ports.size(); ++otheridx) {
+ if (idx == otheridx)
+ continue;
+
+ bool reverse;
+ PortPath& pp(portpath_bidir(idx, otheridx, reverse));
+
+ if (pp.cost < 0) {
+ // Lazily discover routes between ports
+ connect_port(owner().egbase(), idx);
+ }
+
+ if (pp.cost >= 0) {
+ // TODO: keep statistics on average transport time instead of using the arbitrary 2x factor
+ RoutingNodeNeighbour neighb(&m_ports[otheridx]->base_flag(), 2 * pp.cost);
+ neighbours.push_back(neighb);
+ }
+ }
+}
+
+void Fleet::add_ship(Ship* ship) {
+ m_ships.push_back(ship);
+ ship->set_fleet(this);
+ if (upcast(Game, game, &owner().egbase())) {
+ if (m_ports.empty())
+ ship->set_economy(*game, 0);
+ else
+ ship->set_economy(*game, m_ports[0]->get_economy());
+ }
+
+ if (m_ships.size() == 1) {
+ check_merge_economy();
+ }
+}
+
+void Fleet::remove_ship(Editor_Game_Base& egbase, Ship* ship) {
+ std::vector<Ship*>::iterator it = std::find(m_ships.begin(), m_ships.end(), ship);
+ if (it != m_ships.end()) {
+ *it = m_ships.back();
+ m_ships.pop_back();
+ }
+ ship->set_fleet(0);
+ if (upcast(Game, game, &egbase))
+ ship->set_economy(*game, 0);
+
+ if (ship->get_destination(egbase))
+ update(egbase);
+
+ if (m_ships.empty()) {
+ if (m_ports.empty()) {
+ remove(egbase);
+ } else {
+ Flag& base = m_ports[0]->base_flag();
+ for (uint32_t i = 1; i < m_ports.size(); ++i) {
+ // since two ports can be connected by land, it is possible that
+ // disconnecting a previous port also disconnects later ports
+ if (base.get_economy() == m_ports[i]->base_flag().get_economy())
+ Economy::check_split(base, m_ports[i]->base_flag());
+ }
+ }
+ }
}
struct StepEvalFindPorts {
- struct Target {
- uint32_t idx;
- Coords pos;
- };
- std::vector<Target> targets;
-
- int32_t estimate(Map & map, FCoords pos) const
- {
- int32_t est = std::numeric_limits<int32_t>::max();
- container_iterate_const(std::vector<Target>, targets, it) {
- est = std::min(est, map.calc_cost_estimate(pos, it.current->pos));
- }
- return std::max(0, est - 5 * map.calc_cost(0));
- }
-
- int32_t stepcost(Map & map, FCoords from, int32_t /* fromcost */, WalkingDir dir, FCoords to) const
- {
- if (!(to.field->nodecaps() & MOVECAPS_SWIM))
- return -1;
-
- return map.calc_bidi_cost(from, dir);
- }
+ struct Target {
+ uint32_t idx;
+ Coords pos;
+ };
+ std::vector<Target> targets;
+
+ int32_t estimate(Map& map, FCoords pos) const {
+ int32_t est = std::numeric_limits<int32_t>::max();
+ container_iterate_const(std::vector<Target>, targets, it) {
+ est = std::min(est, map.calc_cost_estimate(pos, it.current->pos));
+ }
+ return std::max(0, est - 5 * map.calc_cost(0));
+ }
+
+ int32_t
+ stepcost(Map& map, FCoords from, int32_t /* fromcost */, WalkingDir dir, FCoords to) const {
+ if (!(to.field->nodecaps() & MOVECAPS_SWIM))
+ return -1;
+
+ return map.calc_bidi_cost(from, dir);
+ }
};
/**
@@ -425,126 +400,121 @@
* Note that this is done lazily, i.e. the first time a path is actually requested,
* because path finding is flaky during map loading.
*/
-void Fleet::connect_port(Editor_Game_Base & egbase, uint32_t idx)
-{
- Map & map = egbase.map();
- StepEvalFindPorts se;
-
- for (uint32_t i = 0; i < m_ports.size(); ++i) {
- if (i == idx)
- continue;
-
- bool reverse;
- if (portpath_bidir(i, idx, reverse).cost >= 0)
- continue;
-
- StepEvalFindPorts::Target tgt;
- tgt.idx = i;
- tgt.pos = m_ports[i]->get_warehouse()->get_position();
- se.targets.push_back(tgt);
- }
-
- if (se.targets.empty())
- return;
-
- MapAStar<StepEvalFindPorts> astar(map, se);
-
- BaseImmovable::PositionList src(m_ports[idx]->get_positions(egbase));
- container_iterate_const(BaseImmovable::PositionList, src, it) {
- astar.push(*it.current);
- }
-
- int32_t cost;
- FCoords cur;
- while (!se.targets.empty() && astar.step(cur, cost)) {
- BaseImmovable * imm = cur.field->get_immovable();
- if (!imm || imm->get_type() != PORTDOCK)
- continue;
-
- if (upcast(PortDock, pd, imm)) {
- if (pd->get_owner() != get_owner())
- continue;
-
- if (pd->get_fleet() && pd->get_fleet() != this) {
- log("Fleet::connect_port: different fleets despite reachability\n");
- continue;
- }
-
- uint32_t otheridx = std::find(m_ports.begin(), m_ports.end(), pd) - m_ports.begin();
- if (idx == otheridx)
- continue;
-
- bool reverse;
- PortPath & ppath(portpath_bidir(idx, otheridx, reverse));
-
- if (ppath.cost >= 0)
- continue;
-
- ppath.cost = cost;
- ppath.path.reset(new Path);
- astar.pathto(cur, *ppath.path);
- if (reverse)
- ppath.path->reverse();
-
- container_iterate(std::vector<StepEvalFindPorts::Target>, se.targets, it) {
- if (it.current->idx == otheridx) {
- *it.current = se.targets.back();
- se.targets.pop_back();
- break;
- }
- }
- }
- }
-
- if (!se.targets.empty()) {
- log("Fleet::connect_port: Could not reach all ports!\n");
- }
-}
-
-void Fleet::add_port(Editor_Game_Base & /* egbase */, PortDock * port)
-{
- m_ports.push_back(port);
- port->set_fleet(this);
- if (m_ports.size() == 1) {
- set_economy(m_ports[0]->get_economy());
- } else {
- if (!m_ships.empty())
- m_ports[0]->get_economy()->check_merge(m_ports[0]->base_flag(), port->base_flag());
- }
-
- m_portpaths.resize((m_ports.size() * (m_ports.size() - 1)) / 2);
-}
-
-void Fleet::remove_port(Editor_Game_Base & egbase, PortDock * port)
-{
- std::vector<PortDock *>::iterator it = std::find(m_ports.begin(), m_ports.end(), port);
- if (it != m_ports.end()) {
- uint32_t gap = it - m_ports.begin();
- for (uint32_t i = 0; i < gap; ++i) {
- portpath(i, gap) = portpath(i, m_ports.size() - 1);
- }
- for (uint32_t i = gap + 1; i < m_ports.size() - 1; ++i) {
- portpath(gap, i) = portpath(i, m_ports.size() - 1);
- if (portpath(gap, i).path)
- portpath(gap, i).path->reverse();
- }
- m_portpaths.resize((m_ports.size() * (m_ports.size() - 1)) / 2);
-
- *it = m_ports.back();
- m_ports.pop_back();
- }
- port->set_fleet(0);
-
- if (m_ports.empty()) {
- set_economy(0);
- } else {
- set_economy(m_ports[0]->get_economy());
- if (!m_ships.empty())
- Economy::check_split(m_ports[0]->base_flag(), port->base_flag());
- }
-
- if (m_ships.empty() && m_ports.empty())
- remove(egbase);
+void Fleet::connect_port(Editor_Game_Base& egbase, uint32_t idx) {
+ Map& map = egbase.map();
+ StepEvalFindPorts se;
+
+ for (uint32_t i = 0; i < m_ports.size(); ++i) {
+ if (i == idx)
+ continue;
+
+ bool reverse;
+ if (portpath_bidir(i, idx, reverse).cost >= 0)
+ continue;
+
+ StepEvalFindPorts::Target tgt;
+ tgt.idx = i;
+ tgt.pos = m_ports[i]->get_warehouse()->get_position();
+ se.targets.push_back(tgt);
+ }
+
+ if (se.targets.empty())
+ return;
+
+ MapAStar<StepEvalFindPorts> astar(map, se);
+
+ BaseImmovable::PositionList src(m_ports[idx]->get_positions(egbase));
+ container_iterate_const(BaseImmovable::PositionList, src, it) { astar.push(*it.current); }
+
+ int32_t cost;
+ FCoords cur;
+ while (!se.targets.empty() && astar.step(cur, cost)) {
+ BaseImmovable* imm = cur.field->get_immovable();
+ if (!imm || imm->get_type() != PORTDOCK)
+ continue;
+
+ if (upcast(PortDock, pd, imm)) {
+ if (pd->get_owner() != get_owner())
+ continue;
+
+ if (pd->get_fleet() && pd->get_fleet() != this) {
+ log("Fleet::connect_port: different fleets despite reachability\n");
+ continue;
+ }
+
+ uint32_t otheridx = std::find(m_ports.begin(), m_ports.end(), pd) - m_ports.begin();
+ if (idx == otheridx)
+ continue;
+
+ bool reverse;
+ PortPath& ppath(portpath_bidir(idx, otheridx, reverse));
+
+ if (ppath.cost >= 0)
+ continue;
+
+ ppath.cost = cost;
+ ppath.path.reset(new Path);
+ astar.pathto(cur, *ppath.path);
+ if (reverse)
+ ppath.path->reverse();
+
+ container_iterate(std::vector<StepEvalFindPorts::Target>, se.targets, it) {
+ if (it.current->idx == otheridx) {
+ *it.current = se.targets.back();
+ se.targets.pop_back();
+ break;
+ }
+ }
+ }
+ }
+
+ if (!se.targets.empty()) {
+ log("Fleet::connect_port: Could not reach all ports!\n");
+ }
+}
+
+void Fleet::add_port(Editor_Game_Base& /* egbase */, PortDock* port) {
+ m_ports.push_back(port);
+ port->set_fleet(this);
+ if (m_ports.size() == 1) {
+ set_economy(m_ports[0]->get_economy());
+ } else {
+ if (!m_ships.empty())
+ m_ports[0]->get_economy()->check_merge(m_ports[0]->base_flag(), port->base_flag());
+ }
+
+ m_portpaths.resize((m_ports.size() * (m_ports.size() - 1)) / 2);
+}
+
+void Fleet::remove_port(Editor_Game_Base& egbase, PortDock* port) {
+ std::vector<PortDock*>::iterator it = std::find(m_ports.begin(), m_ports.end(), port);
+ if (it != m_ports.end()) {
+ uint32_t gap = it - m_ports.begin();
+ for (uint32_t i = 0; i < gap; ++i) {
+ portpath(i, gap) = portpath(i, m_ports.size() - 1);
+ }
+ for (uint32_t i = gap + 1; i < m_ports.size() - 1; ++i) {
+ portpath(gap, i) = portpath(i, m_ports.size() - 1);
+ if (portpath(gap, i).path)
+ portpath(gap, i).path->reverse();
+ }
+ m_portpaths.resize((m_ports.size() * (m_ports.size() - 1)) / 2);
+
+ *it = m_ports.back();
+ m_ports.pop_back();
+ }
+ port->set_fleet(0);
+
+ if (m_ports.empty()) {
+ set_economy(0);
+ } else {
+ set_economy(m_ports[0]->get_economy());
+ if (!m_ships.empty())
+ Economy::check_split(m_ports[0]->base_flag(), port->base_flag());
+ }
+
+ if (m_ships.empty() && m_ports.empty())
+ remove(egbase);
}
/**
@@ -552,38 +522,35 @@
*
* @return the dock, or 0 if not found.
*/
-PortDock * Fleet::get_dock(Flag & flag) const
-{
- container_iterate_const(std::vector<PortDock *>, m_ports, portit) {
- if (&(*portit.current)->base_flag() == &flag)
- return *portit.current;
- }
+PortDock* Fleet::get_dock(Flag& flag) const {
+ container_iterate_const(std::vector<PortDock*>, m_ports, portit) {
+ if (&(*portit.current)->base_flag() == &flag)
+ return *portit.current;
+ }
- return 0;
+ return 0;
}
/**
* @return an arbitrary dock of the fleet, or 0 if the fleet has no docks
*/
-PortDock * Fleet::get_arbitrary_dock() const
-{
- if (m_ports.empty())
- return 0;
- return m_ports[0];
+PortDock* Fleet::get_arbitrary_dock() const {
+ if (m_ports.empty())
+ return 0;
+ return m_ports[0];
}
/**
* Trigger an update of ship scheduling
*/
-void Fleet::update(Editor_Game_Base & egbase)
-{
- if (m_act_pending)
- return;
+void Fleet::update(Editor_Game_Base& egbase) {
+ if (m_act_pending)
+ return;
- if (upcast(Game, game, &egbase)) {
- schedule_act(*game, 100);
- m_act_pending = true;
- }
+ if (upcast(Game, game, &egbase)) {
+ schedule_act(*game, 100);
+ m_act_pending = true;
+ }
}
/**
@@ -592,194 +559,186 @@
*
* @note Do not call this directly; instead, trigger it via @ref update
*/
-void Fleet::act(Game & game, uint32_t /* data */)
-{
- m_act_pending = false;
-
- if (!active())
- return;
-
- molog("Fleet::act\n");
-
- container_iterate_const(std::vector<Ship *>, m_ships, shipit) {
- Ship & ship = **shipit.current;
- if (ship.get_nritems() > 0 && !ship.get_destination(game)) {
- molog("Ship %u has items\n", ship.serial());
- container_iterate(std::vector<ShippingItem>, ship.m_items, it) {
- PortDock * dst = it->get_destination(game);
- if (dst) {
- molog("... sending to portdock %u\n", dst->serial());
- ship.set_destination(game, *dst);
- break;
- }
- }
- }
- }
-
- if (m_port_roundrobin >= m_ports.size())
- m_port_roundrobin = 0;
-
- uint32_t rr = m_port_roundrobin;
- do {
- PortDock & pd = *m_ports[rr];
-
- if (pd.get_need_ship()) {
- molog("Port %u needs ship\n", pd.serial());
-
- bool success = false;
- container_iterate_const(std::vector<Ship *>, m_ships, shipit) {
- Ship & ship = **shipit.current;
- PortDock * dst = ship.get_destination(game);
- if (dst && dst != &pd)
- continue;
- if (ship.get_nritems() >= ship.get_capacity())
- continue;
-
- molog("... ship %u takes care of it\n", ship.serial());
-
- if (!dst)
- ship.set_destination(game, pd);
-
- success = true;
- break;
- }
-
- if (!success)
- break;
- }
-
- if (++rr >= m_ports.size())
- rr = 0;
- } while (rr != m_port_roundrobin);
+void Fleet::act(Game& game, uint32_t /* data */) {
+ m_act_pending = false;
+
+ if (!active())
+ return;
+
+ molog("Fleet::act\n");
+
+ container_iterate_const(std::vector<Ship*>, m_ships, shipit) {
+ Ship& ship = **shipit.current;
+ if (ship.get_nritems() > 0 && !ship.get_destination(game)) {
+ molog("Ship %u has items\n", ship.serial());
+ container_iterate(std::vector<ShippingItem>, ship.m_items, it) {
+ PortDock* dst = it->get_destination(game);
+ if (dst) {
+ molog("... sending to portdock %u\n", dst->serial());
+ ship.set_destination(game, *dst);
+ break;
+ }
+ }
+ }
+ }
+
+ if (m_port_roundrobin >= m_ports.size())
+ m_port_roundrobin = 0;
+
+ uint32_t rr = m_port_roundrobin;
+ do {
+ PortDock& pd = *m_ports[rr];
+
+ if (pd.get_need_ship()) {
+ molog("Port %u needs ship\n", pd.serial());
+
+ bool success = false;
+ container_iterate_const(std::vector<Ship*>, m_ships, shipit) {
+ Ship& ship = **shipit.current;
+ PortDock* dst = ship.get_destination(game);
+ if (dst && dst != &pd)
+ continue;
+ if (ship.get_nritems() >= ship.get_capacity())
+ continue;
+
+ molog("... ship %u takes care of it\n", ship.serial());
+
+ if (!dst)
+ ship.set_destination(game, pd);
+
+ success = true;
+ break;
+ }
+
+ if (!success)
+ break;
+ }
+
+ if (++rr >= m_ports.size())
+ rr = 0;
+ } while (rr != m_port_roundrobin);
}
-void Fleet::log_general_info(const Editor_Game_Base & egbase)
-{
- Map_Object::log_general_info(egbase);
+void Fleet::log_general_info(const Editor_Game_Base& egbase) {
+ Map_Object::log_general_info(egbase);
- molog
- ("%"PRIuS" ships and %"PRIuS" ports\n", m_ships.size(), m_ports.size());
+ molog("%" PRIuS " ships and %" PRIuS " ports\n", m_ships.size(), m_ports.size());
}
#define FLEET_SAVEGAME_VERSION 3
-Fleet::Loader::Loader()
-{
-}
-
-void Fleet::Loader::load(FileRead & fr, uint8_t version)
-{
- Map_Object::Loader::load(fr);
-
- Fleet & fleet = get<Fleet>();
-
- uint32_t nrships = fr.Unsigned32();
- m_ships.resize(nrships);
- for (uint32_t i = 0; i < nrships; ++i)
- m_ships[i] = fr.Unsigned32();
-
- uint32_t nrports = fr.Unsigned32();
- m_ports.resize(nrports);
- for (uint32_t i = 0; i < nrports; ++i)
- m_ports[i] = fr.Unsigned32();
-
- if (version >= 2) {
- fleet.m_act_pending = fr.Unsigned8();
- if (version < 3)
- fleet.m_act_pending = false;
- fleet.m_port_roundrobin = fr.Unsigned32();
- }
-}
-
-void Fleet::Loader::load_pointers()
-{
- Map_Object::Loader::load_pointers();
-
- Fleet & fleet = get<Fleet>();
-
- // Act commands created during loading are not persistent, so we need to undo any
- // changes to the pending state.
- bool save_act_pending = fleet.m_act_pending;
-
- container_iterate_const(std::vector<uint32_t>, m_ships, it) {
- fleet.m_ships.push_back(&mol().get<Ship>(*it));
- fleet.m_ships.back()->set_fleet(&fleet);
- }
- container_iterate_const(std::vector<uint32_t>, m_ports, it) {
- fleet.m_ports.push_back(&mol().get<PortDock>(*it));
- fleet.m_ports.back()->set_fleet(&fleet);
- }
-
- fleet.m_portpaths.resize((fleet.m_ports.size() * (fleet.m_ports.size() - 1)) / 2);
-
- fleet.m_act_pending = save_act_pending;
-}
-
-void Fleet::Loader::load_finish()
-{
- Map_Object::Loader::load_finish();
-
- Fleet & fleet = get<Fleet>();
-
- if (!fleet.m_ports.empty()) {
- if (!fleet.m_ships.empty())
- fleet.check_merge_economy();
-
- fleet.set_economy(fleet.m_ports[0]->get_economy());
- }
-}
-
-Map_Object::Loader * Fleet::load
- (Editor_Game_Base & egbase, Map_Map_Object_Loader & mol, FileRead & fr)
-{
- std::auto_ptr<Loader> loader(new Loader);
-
- try {
- // The header has been peeled away by the caller
-
- uint8_t const version = fr.Unsigned8();
- if (1 <= version && version <= FLEET_SAVEGAME_VERSION) {
- Player_Number owner_number = fr.Unsigned8();
- if (!owner_number || owner_number > egbase.map().get_nrplayers())
- throw game_data_error
- ("owner number is %u but there are only %u players",
- owner_number, egbase.map().get_nrplayers());
-
- Player * owner = egbase.get_player(owner_number);
- if (!owner)
- throw game_data_error("owning player %u does not exist", owner_number);
-
- loader->init(egbase, mol, *(new Fleet(*owner)));
- loader->load(fr, version);
- } else
- throw game_data_error(_("unknown/unhandled version %u"), version);
- } catch (const std::exception & e) {
- throw wexception(_("loading portdock: %s"), e.what());
- }
-
- return loader.release();
-}
-
-void Fleet::save(Editor_Game_Base & egbase, Map_Map_Object_Saver & mos, FileWrite & fw)
-{
- fw.Unsigned8(header_Fleet);
- fw.Unsigned8(FLEET_SAVEGAME_VERSION);
-
- fw.Unsigned8(m_owner.player_number());
-
- Map_Object::save(egbase, mos, fw);
-
- fw.Unsigned32(m_ships.size());
- container_iterate_const(std::vector<Ship *>, m_ships, it) {
- fw.Unsigned32(mos.get_object_file_index(**it));
- }
- fw.Unsigned32(m_ports.size());
- container_iterate_const(std::vector<PortDock *>, m_ports, it) {
- fw.Unsigned32(mos.get_object_file_index(**it));
- }
-
- fw.Unsigned8(m_act_pending);
- fw.Unsigned32(m_port_roundrobin);
-}
-
-} // namespace Widelands
+Fleet::Loader::Loader() {}
+
+void Fleet::Loader::load(FileRead& fr, uint8_t version) {
+ Map_Object::Loader::load(fr);
+
+ Fleet& fleet = get<Fleet>();
+
+ uint32_t nrships = fr.Unsigned32();
+ m_ships.resize(nrships);
+ for (uint32_t i = 0; i < nrships; ++i)
+ m_ships[i] = fr.Unsigned32();
+
+ uint32_t nrports = fr.Unsigned32();
+ m_ports.resize(nrports);
+ for (uint32_t i = 0; i < nrports; ++i)
+ m_ports[i] = fr.Unsigned32();
+
+ if (version >= 2) {
+ fleet.m_act_pending = fr.Unsigned8();
+ if (version < 3)
+ fleet.m_act_pending = false;
+ fleet.m_port_roundrobin = fr.Unsigned32();
+ }
+}
+
+void Fleet::Loader::load_pointers() {
+ Map_Object::Loader::load_pointers();
+
+ Fleet& fleet = get<Fleet>();
+
+ // Act commands created during loading are not persistent, so we need to undo any
+ // changes to the pending state.
+ bool save_act_pending = fleet.m_act_pending;
+
+ container_iterate_const(std::vector<uint32_t>, m_ships, it) {
+ fleet.m_ships.push_back(&mol().get<Ship>(*it));
+ fleet.m_ships.back()->set_fleet(&fleet);
+ }
+ container_iterate_const(std::vector<uint32_t>, m_ports, it) {
+ fleet.m_ports.push_back(&mol().get<PortDock>(*it));
+ fleet.m_ports.back()->set_fleet(&fleet);
+ }
+
+ fleet.m_portpaths.resize((fleet.m_ports.size() * (fleet.m_ports.size() - 1)) / 2);
+
+ fleet.m_act_pending = save_act_pending;
+}
+
+void Fleet::Loader::load_finish() {
+ Map_Object::Loader::load_finish();
+
+ Fleet& fleet = get<Fleet>();
+
+ if (!fleet.m_ports.empty()) {
+ if (!fleet.m_ships.empty())
+ fleet.check_merge_economy();
+
+ fleet.set_economy(fleet.m_ports[0]->get_economy());
+ }
+}
+
+Map_Object::Loader* Fleet::load(Editor_Game_Base& egbase,
+ Map_Map_Object_Loader& mol,
+ FileRead& fr) {
+ std::auto_ptr<Loader> loader(new Loader);
+
+ try {
+ // The header has been peeled away by the caller
+
+ uint8_t const version = fr.Unsigned8();
+ if (1 <= version && version <= FLEET_SAVEGAME_VERSION) {
+ Player_Number owner_number = fr.Unsigned8();
+ if (!owner_number || owner_number > egbase.map().get_nrplayers())
+ throw game_data_error("owner number is %u but there are only %u players",
+ owner_number,
+ egbase.map().get_nrplayers());
+
+ Player* owner = egbase.get_player(owner_number);
+ if (!owner)
+ throw game_data_error("owning player %u does not exist", owner_number);
+
+ loader->init(egbase, mol, *(new Fleet(*owner)));
+ loader->load(fr, version);
+ } else
+ throw game_data_error(_("unknown/unhandled version %u"), version);
+ }
+ catch (const std::exception & e) {
+ throw wexception(_("loading portdock: %s"), e.what());
+ }
+
+ return loader.release();
+}
+
+void Fleet::save(Editor_Game_Base& egbase, Map_Map_Object_Saver& mos, FileWrite& fw) {
+ fw.Unsigned8(header_Fleet);
+ fw.Unsigned8(FLEET_SAVEGAME_VERSION);
+
+ fw.Unsigned8(m_owner.player_number());
+
+ Map_Object::save(egbase, mos, fw);
+
+ fw.Unsigned32(m_ships.size());
+ container_iterate_const(std::vector<Ship*>, m_ships, it) {
+ fw.Unsigned32(mos.get_object_file_index(**it));
+ }
+ fw.Unsigned32(m_ports.size());
+ container_iterate_const(std::vector<PortDock*>, m_ports, it) {
+ fw.Unsigned32(mos.get_object_file_index(**it));
+ }
+
+ fw.Unsigned8(m_act_pending);
+ fw.Unsigned32(m_port_roundrobin);
+}
+
+} // namespace Widelands
=== modified file 'src/economy/fleet.h'
--- src/economy/fleet.h 2013-04-22 20:15:00 +0000
+++ src/economy/fleet.h 2013-05-18 05:56:27 +0000
@@ -51,92 +51,91 @@
* properly at the moment.
*/
struct Fleet : Map_Object {
- struct PortPath {
- int32_t cost;
- boost::shared_ptr<Path> path;
-
- PortPath() : cost(-1) {}
- };
-
- Fleet(Player & player);
-
- Player * get_owner() const {return &m_owner;}
- Player & owner() const {return m_owner;}
-
- PortDock * get_dock(Flag & flag) const;
- PortDock * get_arbitrary_dock() const;
- void set_economy(Economy * e);
-
- bool active() const;
-
- virtual int32_t get_type() const throw ();
- virtual char const * type_name() const throw ();
-
- virtual void init(Editor_Game_Base &);
- virtual void cleanup(Editor_Game_Base &);
- void update(Editor_Game_Base &);
-
- void add_ship(Ship * ship);
- void remove_ship(Editor_Game_Base & egbase, Ship * ship);
- void add_port(Editor_Game_Base & egbase, PortDock * port);
- void remove_port(Editor_Game_Base & egbase, PortDock * port);
-
- virtual void log_general_info(const Editor_Game_Base &);
-
- bool get_path(PortDock & start, PortDock & end, Path & path);
- void add_neighbours(PortDock & pd, std::vector<RoutingNodeNeighbour> & neighbours);
-
-protected:
- virtual void act(Game &, uint32_t data);
-
-private:
- void find_other_fleet(Editor_Game_Base & egbase);
- void merge(Editor_Game_Base & egbase, Fleet * other);
- void check_merge_economy();
- void connect_port(Editor_Game_Base & egbase, uint32_t idx);
-
- PortPath & portpath(uint32_t i, uint32_t j);
- const PortPath & portpath(uint32_t i, uint32_t j) const;
- PortPath & portpath_bidir(uint32_t i, uint32_t j, bool & reverse);
- const PortPath & portpath_bidir(uint32_t i, uint32_t j, bool & reverse) const;
-
- Player & m_owner;
- std::vector<Ship *> m_ships;
- std::vector<PortDock *> m_ports;
-
- bool m_act_pending;
- uint32_t m_port_roundrobin;
-
- /**
- * Store all pairs shortest paths between port docks
- *
- * Let i < j, then the path from m_ports[i] to m_ports[j] is stored in
- * m_portpaths[binom(j,2) + i]
- */
- std::vector<PortPath> m_portpaths;
-
- // saving and loading
-protected:
- struct Loader : Map_Object::Loader {
- Loader();
-
- void load(FileRead &, uint8_t version);
- virtual void load_pointers();
- virtual void load_finish();
-
- private:
- std::vector<uint32_t> m_ships;
- std::vector<uint32_t> m_ports;
- };
-
-public:
- virtual bool has_new_save_support() {return true;}
- virtual void save(Editor_Game_Base &, Map_Map_Object_Saver &, FileWrite &);
-
- static Map_Object::Loader * load
- (Editor_Game_Base &, Map_Map_Object_Loader &, FileRead &);
+ struct PortPath {
+ int32_t cost;
+ boost::shared_ptr<Path> path;
+
+ PortPath() : cost(-1) {}
+ };
+
+ Fleet(Player& player);
+
+ Player* get_owner() const { return &m_owner; }
+ Player& owner() const { return m_owner; }
+
+ PortDock* get_dock(Flag& flag) const;
+ PortDock* get_arbitrary_dock() const;
+ void set_economy(Economy* e);
+
+ bool active() const;
+
+ virtual int32_t get_type() const throw();
+ virtual char const* type_name() const throw();
+
+ virtual void init(Editor_Game_Base&);
+ virtual void cleanup(Editor_Game_Base&);
+ void update(Editor_Game_Base&);
+
+ void add_ship(Ship* ship);
+ void remove_ship(Editor_Game_Base& egbase, Ship* ship);
+ void add_port(Editor_Game_Base& egbase, PortDock* port);
+ void remove_port(Editor_Game_Base& egbase, PortDock* port);
+
+ virtual void log_general_info(const Editor_Game_Base&);
+
+ bool get_path(PortDock& start, PortDock& end, Path& path);
+ void add_neighbours(PortDock& pd, std::vector<RoutingNodeNeighbour>& neighbours);
+
+ protected:
+ virtual void act(Game&, uint32_t data);
+
+ private:
+ void find_other_fleet(Editor_Game_Base& egbase);
+ void merge(Editor_Game_Base& egbase, Fleet* other);
+ void check_merge_economy();
+ void connect_port(Editor_Game_Base& egbase, uint32_t idx);
+
+ PortPath& portpath(uint32_t i, uint32_t j);
+ const PortPath& portpath(uint32_t i, uint32_t j) const;
+ PortPath& portpath_bidir(uint32_t i, uint32_t j, bool& reverse);
+ const PortPath& portpath_bidir(uint32_t i, uint32_t j, bool& reverse) const;
+
+ Player& m_owner;
+ std::vector<Ship*> m_ships;
+ std::vector<PortDock*> m_ports;
+
+ bool m_act_pending;
+ uint32_t m_port_roundrobin;
+
+ /**
+ * Store all pairs shortest paths between port docks
+ *
+ * Let i < j, then the path from m_ports[i] to m_ports[j] is stored in
+ * m_portpaths[binom(j,2) + i]
+ */
+ std::vector<PortPath> m_portpaths;
+
+ // saving and loading
+ protected:
+ struct Loader : Map_Object::Loader {
+ Loader();
+
+ void load(FileRead&, uint8_t version);
+ virtual void load_pointers();
+ virtual void load_finish();
+
+ private:
+ std::vector<uint32_t> m_ships;
+ std::vector<uint32_t> m_ports;
+ };
+
+ public:
+ virtual bool has_new_save_support() { return true; }
+ virtual void save(Editor_Game_Base&, Map_Map_Object_Saver&, FileWrite&);
+
+ static Map_Object::Loader* load(Editor_Game_Base&, Map_Map_Object_Loader&, FileRead&);
};
-} // namespace Widelands
+} // namespace Widelands
-#endif // ECONOMY_FLEET_H
+#endif // ECONOMY_FLEET_H
=== modified file 'src/economy/idleworkersupply.cc'
--- src/economy/idleworkersupply.cc 2013-02-10 19:36:24 +0000
+++ src/economy/idleworkersupply.cc 2013-05-18 05:56:27 +0000
@@ -36,104 +36,75 @@
/**
* Automatically register with the worker's economy.
*/
-IdleWorkerSupply::IdleWorkerSupply(Worker & w) : m_worker (w), m_economy(0)
-{
- set_economy(w.get_economy());
+IdleWorkerSupply::IdleWorkerSupply(Worker& w) : m_worker(w), m_economy(0) {
+ set_economy(w.get_economy());
}
-
/**
* Automatically unregister from economy.
*/
-IdleWorkerSupply::~IdleWorkerSupply()
-{
- set_economy(0);
-}
-
+IdleWorkerSupply::~IdleWorkerSupply() { set_economy(0); }
/**
* Add/remove this supply from the Economy as appropriate.
*/
-void IdleWorkerSupply::set_economy(Economy * const e)
-{
- if (m_economy != e) {
- if (m_economy)
- m_economy->remove_supply(*this);
- if ((m_economy = e))
- m_economy-> add_supply(*this);
- }
+void IdleWorkerSupply::set_economy(Economy* const e) {
+ if (m_economy != e) {
+ if (m_economy)
+ m_economy->remove_supply(*this);
+ if ((m_economy = e))
+ m_economy->add_supply(*this);
+ }
}
/**
* Worker is walking around the road network, so active by definition.
*/
-bool IdleWorkerSupply::is_active() const throw ()
-{
- return true;
-}
-
-bool IdleWorkerSupply::has_storage() const throw ()
-{
- return m_worker.get_transfer();
-}
-
-void IdleWorkerSupply::get_ware_type(WareWorker & type, Ware_Index & ware) const
-{
- type = wwWORKER;
- ware = m_worker.worker_index();
+bool IdleWorkerSupply::is_active() const throw() { return true; }
+
+bool IdleWorkerSupply::has_storage() const throw() { return m_worker.get_transfer(); }
+
+void IdleWorkerSupply::get_ware_type(WareWorker& type, Ware_Index& ware) const {
+ type = wwWORKER;
+ ware = m_worker.worker_index();
}
/**
* Return the worker's position.
*/
-PlayerImmovable * IdleWorkerSupply::get_position(Game & game)
-{
- return m_worker.get_location(game);
-}
-
-
-uint32_t IdleWorkerSupply::nr_supplies(const Game &, const Request & req) const
-{
- assert
- (req.get_type() != wwWORKER or
- req.get_index() < m_worker.descr().tribe().get_nrworkers());
- if
- (req.get_type() == wwWORKER &&
- m_worker.descr().can_act_as(req.get_index()) &&
- req.get_requirements().check(m_worker))
- return 1;
-
- return 0;
-}
-
-WareInstance & IdleWorkerSupply::launch_item(Game &, const Request &)
-{
- throw wexception("IdleWorkerSupply::launch_item() makes no sense.");
-}
-
+PlayerImmovable* IdleWorkerSupply::get_position(Game& game) { return m_worker.get_location(game); }
+
+uint32_t IdleWorkerSupply::nr_supplies(const Game&, const Request& req) const {
+ assert(req.get_type() != wwWORKER or req.get_index() < m_worker.descr().tribe().get_nrworkers());
+ if (req.get_type() == wwWORKER && m_worker.descr().can_act_as(req.get_index()) &&
+ req.get_requirements().check(m_worker))
+ return 1;
+
+ return 0;
+}
+
+WareInstance& IdleWorkerSupply::launch_item(Game&, const Request&) {
+ throw wexception("IdleWorkerSupply::launch_item() makes no sense.");
+}
/**
* No need to explicitly launch the worker.
*/
-Worker & IdleWorkerSupply::launch_worker(Game &, const Request & req)
-{
- if (req.get_type() != wwWORKER)
- throw wexception("IdleWorkerSupply: not a worker request");
- if
- (!m_worker.descr().can_act_as(req.get_index()) ||
- !req.get_requirements().check(m_worker))
- throw wexception("IdleWorkerSupply: worker type mismatch");
+Worker& IdleWorkerSupply::launch_worker(Game&, const Request& req) {
+ if (req.get_type() != wwWORKER)
+ throw wexception("IdleWorkerSupply: not a worker request");
+ if (!m_worker.descr().can_act_as(req.get_index()) || !req.get_requirements().check(m_worker))
+ throw wexception("IdleWorkerSupply: worker type mismatch");
- return m_worker;
+ return m_worker;
}
-void IdleWorkerSupply::send_to_storage(Game & game, Warehouse * wh)
-{
- assert(!has_storage());
+void IdleWorkerSupply::send_to_storage(Game& game, Warehouse* wh) {
+ assert(!has_storage());
- Transfer * t = new Transfer(game, m_worker);
- t->set_destination(*wh);
- m_worker.start_task_transfer(game, t);
+ Transfer* t = new Transfer(game, m_worker);
+ t->set_destination(*wh);
+ m_worker.start_task_transfer(game, t);
}
}
=== modified file 'src/economy/idleworkersupply.h'
--- src/economy/idleworkersupply.h 2013-04-22 20:15:00 +0000
+++ src/economy/idleworkersupply.h 2013-05-18 05:56:27 +0000
@@ -31,24 +31,24 @@
class Economy;
struct IdleWorkerSupply : public Supply {
- IdleWorkerSupply(Worker &);
- ~IdleWorkerSupply();
-
- void set_economy(Economy *);
- virtual PlayerImmovable * get_position(Game &);
-
- virtual bool is_active() const throw ();
- virtual bool has_storage() const throw ();
- virtual void get_ware_type(WareWorker & type, Ware_Index & ware) const;
- virtual void send_to_storage(Game &, Warehouse * wh);
-
- virtual uint32_t nr_supplies(const Game &, const Request &) const;
- virtual WareInstance & launch_item(Game &, const Request &);
- virtual Worker & launch_worker(Game &, const Request &);
-
-private:
- Worker & m_worker;
- Economy * m_economy;
+ IdleWorkerSupply(Worker&);
+ ~IdleWorkerSupply();
+
+ void set_economy(Economy*);
+ virtual PlayerImmovable* get_position(Game&);
+
+ virtual bool is_active() const throw();
+ virtual bool has_storage() const throw();
+ virtual void get_ware_type(WareWorker& type, Ware_Index& ware) const;
+ virtual void send_to_storage(Game&, Warehouse* wh);
+
+ virtual uint32_t nr_supplies(const Game&, const Request&) const;
+ virtual WareInstance& launch_item(Game&, const Request&);
+ virtual Worker& launch_worker(Game&, const Request&);
+
+ private:
+ Worker& m_worker;
+ Economy* m_economy;
};
}
=== modified file 'src/economy/iroute.h'
--- src/economy/iroute.h 2012-03-03 19:23:20 +0000
+++ src/economy/iroute.h 2013-05-18 05:56:27 +0000
@@ -38,10 +38,10 @@
* interface
**/
struct IRoute {
- virtual ~IRoute() {};
+ virtual ~IRoute() {}
- virtual void init(int32_t) = 0;
- virtual void insert_as_first(RoutingNode * node) = 0;
+ virtual void init(int32_t) = 0;
+ virtual void insert_as_first(RoutingNode* node) = 0;
};
}
=== modified file 'src/economy/itransport_cost_calculator.h'
--- src/economy/itransport_cost_calculator.h 2012-02-15 21:25:34 +0000
+++ src/economy/itransport_cost_calculator.h 2013-05-18 05:56:27 +0000
@@ -34,9 +34,9 @@
* but most economy code doesn't need all of maps functionality
*/
struct ITransportCostCalculator : boost::noncopyable {
- virtual ~ITransportCostCalculator() {}
+ virtual ~ITransportCostCalculator() {}
- virtual int32_t calc_cost_estimate(Coords, Coords) const = 0;
+ virtual int32_t calc_cost_estimate(Coords, Coords) const = 0;
};
}
=== modified file 'src/economy/portdock.cc'
--- src/economy/portdock.cc 2013-02-11 18:01:26 +0000
+++ src/economy/portdock.cc 2013-05-18 05:56:27 +0000
@@ -35,13 +35,8 @@
Map_Object_Descr portdock_descr("portdock", "Port Dock");
-PortDock::PortDock() :
- PlayerImmovable(portdock_descr),
- m_fleet(0),
- m_warehouse(0),
- m_need_ship(false)
-{
-}
+PortDock::PortDock()
+ : PlayerImmovable(portdock_descr), m_fleet(0), m_warehouse(0), m_need_ship(false) {}
/**
* Add a position where ships may dock.
@@ -53,19 +48,15 @@
*
* @note This only works properly when called before @ref init
*/
-void PortDock::add_position(Coords where)
-{
- m_dockpoints.push_back(where);
-}
+void PortDock::add_position(Coords where) { m_dockpoints.push_back(where); }
/**
* Set the @ref Warehouse buddy of this dock. May only be called once.
*/
-void PortDock::set_warehouse(Warehouse * wh)
-{
- assert(!m_warehouse);
+void PortDock::set_warehouse(Warehouse* wh) {
+ assert(!m_warehouse);
- m_warehouse = wh;
+ m_warehouse = wh;
}
/**
@@ -73,51 +64,30 @@
*
* @warning This should only be called via @ref Fleet itself.
*/
-void PortDock::set_fleet(Fleet * fleet)
-{
- m_fleet = fleet;
-}
-
-int32_t PortDock::get_size() const throw ()
-{
- return SMALL;
-}
-
-bool PortDock::get_passable() const throw ()
-{
- return true;
-}
-
-int32_t PortDock::get_type() const throw ()
-{
- return PORTDOCK;
-}
-
-char const * PortDock::type_name() const throw ()
-{
- return "portdock";
-}
-
-PortDock::PositionList PortDock::get_positions
- (const Editor_Game_Base &) const throw ()
-{
- return m_dockpoints;
-}
-
-Flag & PortDock::base_flag()
-{
- return m_warehouse->base_flag();
-}
+void PortDock::set_fleet(Fleet* fleet) { m_fleet = fleet; }
+
+int32_t PortDock::get_size() const throw() { return SMALL; }
+
+bool PortDock::get_passable() const throw() { return true; }
+
+int32_t PortDock::get_type() const throw() { return PORTDOCK; }
+
+char const* PortDock::type_name() const throw() { return "portdock"; }
+
+PortDock::PositionList PortDock::get_positions(const Editor_Game_Base&) const throw() {
+ return m_dockpoints;
+}
+
+Flag& PortDock::base_flag() { return m_warehouse->base_flag(); }
/**
* Return the dock that has the given flag as its base, or 0 if no dock of our fleet
* has the given flag.
*/
-PortDock * PortDock::get_dock(Flag & flag) const
-{
- if (m_fleet)
- return m_fleet->get_dock(flag);
- return 0;
+PortDock* PortDock::get_dock(Flag& flag) const {
+ if (m_fleet)
+ return m_fleet->get_dock(flag);
+ return 0;
}
/**
@@ -126,345 +96,309 @@
* Called by @ref Warehouse::set_economy, and responsible for forwarding the
* change to @ref Fleet.
*/
-void PortDock::set_economy(Economy * e)
-{
- if (e == get_economy())
- return;
-
- PlayerImmovable::set_economy(e);
- if (m_fleet)
- m_fleet->set_economy(e);
-
- if (upcast(Game, game, &owner().egbase())) {
- container_iterate(std::vector<ShippingItem>, m_waiting, it) {
- it->set_economy(*game, e);
- }
- }
-}
-
-
-void PortDock::draw
- (const Editor_Game_Base &, RenderTarget &, const FCoords, const Point)
-{
- // do nothing
-}
-
-const std::string & PortDock::name() const throw ()
-{
- static const std::string name_("portdock");
- return name_;
-}
-
-void PortDock::init(Editor_Game_Base & egbase)
-{
- PlayerImmovable::init(egbase);
-
- container_iterate_const(PositionList, m_dockpoints, it) {
- set_position(egbase, *it.current);
- }
-
- init_fleet(egbase);
+void PortDock::set_economy(Economy* e) {
+ if (e == get_economy())
+ return;
+
+ PlayerImmovable::set_economy(e);
+ if (m_fleet)
+ m_fleet->set_economy(e);
+
+ if (upcast(Game, game, &owner().egbase())) {
+ container_iterate(std::vector<ShippingItem>, m_waiting, it) { it->set_economy(*game, e); }
+ }
+}
+
+void PortDock::draw(const Editor_Game_Base&, RenderTarget&, const FCoords&, const Point&) {
+ // do nothing
+}
+
+const std::string& PortDock::name() const throw() {
+ static const std::string name_("portdock");
+ return name_;
+}
+
+void PortDock::init(Editor_Game_Base& egbase) {
+ PlayerImmovable::init(egbase);
+
+ container_iterate_const(PositionList, m_dockpoints, it) { set_position(egbase, *it.current); }
+
+ init_fleet(egbase);
}
/**
* Create our initial singleton @ref Fleet. The fleet code ensures
* that we merge with a larger fleet when possible.
*/
-void PortDock::init_fleet(Editor_Game_Base & egbase)
-{
- Fleet * fleet = new Fleet(owner());
- fleet->add_port(egbase, this);
- fleet->init(egbase);
- // Note: the Fleet calls our set_fleet automatically
+void PortDock::init_fleet(Editor_Game_Base& egbase) {
+ Fleet* fleet = new Fleet(owner());
+ fleet->add_port(egbase, this);
+ fleet->init(egbase);
+ // Note: the Fleet calls our set_fleet automatically
}
-void PortDock::cleanup(Editor_Game_Base & egbase)
-{
- if (m_warehouse)
- m_warehouse->m_portdock = 0;
-
- if (upcast(Game, game, &egbase)) {
- container_iterate(std::vector<ShippingItem>, m_waiting, it) {
- it.current->remove(*game);
- }
- }
-
- if (m_fleet)
- m_fleet->remove_port(egbase, this);
-
- container_iterate_const(PositionList, m_dockpoints, it) {
- unset_position(egbase, *it.current);
- }
-
- PlayerImmovable::cleanup(egbase);
+void PortDock::cleanup(Editor_Game_Base& egbase) {
+ if (m_warehouse)
+ m_warehouse->m_portdock = 0;
+
+ if (upcast(Game, game, &egbase)) {
+ container_iterate(std::vector<ShippingItem>, m_waiting, it) { it.current->remove(*game); }
+ }
+
+ if (m_fleet)
+ m_fleet->remove_port(egbase, this);
+
+ container_iterate_const(PositionList, m_dockpoints, it) { unset_position(egbase, *it.current); }
+
+ PlayerImmovable::cleanup(egbase);
}
/**
* Add the flags of all ports that can be reached via this dock.
*/
-void PortDock::add_neighbours(std::vector<RoutingNodeNeighbour> & neighbours)
-{
- if (m_fleet && m_fleet->active())
- m_fleet->add_neighbours(*this, neighbours);
+void PortDock::add_neighbours(std::vector<RoutingNodeNeighbour>& neighbours) {
+ if (m_fleet && m_fleet->active())
+ m_fleet->add_neighbours(*this, neighbours);
}
/**
* The given @p ware enters the dock, waiting to be transported away.
*/
-void PortDock::add_shippingitem(Game & game, WareInstance & ware)
-{
- m_waiting.push_back(ShippingItem(ware));
- ware.set_location(game, this);
- ware.update(game);
+void PortDock::add_shippingitem(Game& game, WareInstance& ware) {
+ m_waiting.push_back(ShippingItem(ware));
+ ware.set_location(game, this);
+ ware.update(game);
}
/**
* The given @p ware, which is assumed to be inside the dock, has updated
* its route.
*/
-void PortDock::update_shippingitem(Game & game, WareInstance & ware)
-{
- container_iterate(std::vector<ShippingItem>, m_waiting, it) {
- if (it.current->m_object.serial() == ware.serial()) {
- _update_shippingitem(game, it.current);
- return;
- }
- }
+void PortDock::update_shippingitem(Game& game, WareInstance& ware) {
+ container_iterate(std::vector<ShippingItem>, m_waiting, it) {
+ if (it.current->m_object.serial() == ware.serial()) {
+ _update_shippingitem(game, it.current);
+ return;
+ }
+ }
}
/**
* The given @p worker enters the dock, waiting to be transported away.
*/
-void PortDock::add_shippingitem(Game & game, Worker & worker)
-{
- m_waiting.push_back(ShippingItem(worker));
- worker.set_location(this);
- update_shippingitem(game, worker);
+void PortDock::add_shippingitem(Game& game, Worker& worker) {
+ m_waiting.push_back(ShippingItem(worker));
+ worker.set_location(this);
+ update_shippingitem(game, worker);
}
/**
* The given @p worker, which is assumed to be inside the dock, has
* updated its route.
*/
-void PortDock::update_shippingitem(Game & game, Worker & worker)
-{
- container_iterate(std::vector<ShippingItem>, m_waiting, it) {
- if (it.current->m_object.serial() == worker.serial()) {
- _update_shippingitem(game, it.current);
- return;
- }
- }
+void PortDock::update_shippingitem(Game& game, Worker& worker) {
+ container_iterate(std::vector<ShippingItem>, m_waiting, it) {
+ if (it.current->m_object.serial() == worker.serial()) {
+ _update_shippingitem(game, it.current);
+ return;
+ }
+ }
}
-void PortDock::_update_shippingitem(Game & game, std::vector<ShippingItem>::iterator it)
-{
- it->fetch_destination(game, *this);
-
- PortDock * dst = it->get_destination(game);
- assert(dst != this);
-
- if (dst) {
- set_need_ship(game, true);
- } else {
- it->set_location(game, m_warehouse);
- it->end_shipping(game);
- *it = m_waiting.back();
- m_waiting.pop_back();
-
- if (m_waiting.empty())
- set_need_ship(game, false);
- }
+void PortDock::_update_shippingitem(Game& game, std::vector<ShippingItem>::iterator it) {
+ it->fetch_destination(game, *this);
+
+ PortDock* dst = it->get_destination(game);
+ assert(dst != this);
+
+ if (dst) {
+ set_need_ship(game, true);
+ } else {
+ it->set_location(game, m_warehouse);
+ it->end_shipping(game);
+ *it = m_waiting.back();
+ m_waiting.pop_back();
+
+ if (m_waiting.empty())
+ set_need_ship(game, false);
+ }
}
/**
* A ship has arrived at the dock. Clear all items designated for this dock,
* and load the ship.
*/
-void PortDock::ship_arrived(Game & game, Ship & ship)
-{
- std::vector<ShippingItem> items;
- ship.withdraw_items(game, *this, items);
-
- container_iterate(std::vector<ShippingItem>, items, it) {
- it->set_location(game, m_warehouse);
- it->end_shipping(game);
- }
-
- if (ship.get_nritems() < ship.get_capacity() && !m_waiting.empty()) {
- uint32_t nrload = std::min<uint32_t>(m_waiting.size(), ship.get_capacity() - ship.get_nritems());
-
- while (nrload--) {
- ship.add_item(game, m_waiting.back());
- m_waiting.pop_back();
- }
-
- if (m_waiting.empty())
- set_need_ship(game, false);
- }
-
- m_fleet->update(game);
+void PortDock::ship_arrived(Game& game, Ship& ship) {
+ std::vector<ShippingItem> items;
+ ship.withdraw_items(game, *this, items);
+
+ container_iterate(std::vector<ShippingItem>, items, it) {
+ it->set_location(game, m_warehouse);
+ it->end_shipping(game);
+ }
+
+ if (ship.get_nritems() < ship.get_capacity() && !m_waiting.empty()) {
+ uint32_t nrload =
+ std::min<uint32_t>(m_waiting.size(), ship.get_capacity() - ship.get_nritems());
+
+ while (nrload--) {
+ ship.add_item(game, m_waiting.back());
+ m_waiting.pop_back();
+ }
+
+ if (m_waiting.empty())
+ set_need_ship(game, false);
+ }
+
+ m_fleet->update(game);
}
-void PortDock::set_need_ship(Game & game, bool need)
-{
- molog("set_need_ship(%s)\n", need ? "true" : "false");
-
- if (need == m_need_ship)
- return;
-
- m_need_ship = need;
-
- if (m_fleet) {
- molog("... trigger fleet update\n");
- m_fleet->update(game);
- }
+void PortDock::set_need_ship(Game& game, bool need) {
+ molog("set_need_ship(%s)\n", need ? "true" : "false");
+
+ if (need == m_need_ship)
+ return;
+
+ m_need_ship = need;
+
+ if (m_fleet) {
+ molog("... trigger fleet update\n");
+ m_fleet->update(game);
+ }
}
/**
* Return the number of wares or workers of the given type that are waiting at the dock.
*/
-uint32_t PortDock::count_waiting(WareWorker waretype, Ware_Index wareindex)
-{
- uint32_t count = 0;
-
- container_iterate(std::vector<ShippingItem>, m_waiting, it) {
- WareInstance * ware;
- Worker * worker;
- it.current->get(owner().egbase(), ware, worker);
-
- if (waretype == wwWORKER) {
- if (worker && worker->worker_index() == wareindex)
- count++;
- } else {
- if (ware && ware->descr_index() == wareindex)
- count++;
- }
- }
-
- return count;
+uint32_t PortDock::count_waiting(WareWorker waretype, Ware_Index wareindex) {
+ uint32_t count = 0;
+
+ container_iterate(std::vector<ShippingItem>, m_waiting, it) {
+ WareInstance* ware;
+ Worker* worker;
+ it.current->get(owner().egbase(), ware, worker);
+
+ if (waretype == wwWORKER) {
+ if (worker && worker->worker_index() == wareindex)
+ count++;
+ } else {
+ if (ware && ware->descr_index() == wareindex)
+ count++;
+ }
+ }
+
+ return count;
}
-void PortDock::log_general_info(const Editor_Game_Base & egbase)
-{
- PlayerImmovable::log_general_info(egbase);
-
- Coords pos(m_warehouse->get_position());
- molog
- ("PortDock for warehouse %u (at %i,%i) in fleet %u, need_ship: %s, waiting: %"PRIuS"\n",
- m_warehouse ? m_warehouse->serial() : 0, pos.x, pos.y,
- m_fleet ? m_fleet->serial() : 0,
- m_need_ship ? "true" : "false",
- m_waiting.size());
-
- container_iterate(std::vector<ShippingItem>, m_waiting, it) {
- molog
- (" IT %u, destination %u\n",
- it.current->m_object.serial(),
- it.current->m_destination_dock.serial());
- }
+void PortDock::log_general_info(const Editor_Game_Base& egbase) {
+ PlayerImmovable::log_general_info(egbase);
+
+ Coords pos(m_warehouse->get_position());
+ molog("PortDock for warehouse %u (at %i,%i) in fleet %u, need_ship: %s, waiting: %" PRIuS "\n",
+ m_warehouse ? m_warehouse->serial() : 0,
+ pos.x,
+ pos.y,
+ m_fleet ? m_fleet->serial() : 0,
+ m_need_ship ? "true" : "false",
+ m_waiting.size());
+
+ container_iterate(std::vector<ShippingItem>, m_waiting, it) {
+ molog(" IT %u, destination %u\n",
+ it.current->m_object.serial(),
+ it.current->m_destination_dock.serial());
+ }
}
#define PORTDOCK_SAVEGAME_VERSION 2
-PortDock::Loader::Loader() : m_warehouse(0)
-{
-}
-
-void PortDock::Loader::load(FileRead & fr, uint8_t version)
-{
- PlayerImmovable::Loader::load(fr);
-
- PortDock & pd = get<PortDock>();
-
- m_warehouse = fr.Unsigned32();
- uint16_t nrdockpoints = fr.Unsigned16();
-
- pd.m_dockpoints.resize(nrdockpoints);
- for (uint16_t i = 0; i < nrdockpoints; ++i) {
- pd.m_dockpoints[i] = fr.Coords32(egbase().map().extent());
- pd.set_position(egbase(), pd.m_dockpoints[i]);
- }
-
- if (version >= 2) {
- pd.m_need_ship = fr.Unsigned8();
-
- m_waiting.resize(fr.Unsigned32());
- container_iterate(std::vector<ShippingItem::Loader>, m_waiting, it) {
- it->load(fr);
- }
- }
-}
-
-void PortDock::Loader::load_pointers()
-{
- PlayerImmovable::Loader::load_pointers();
-
- PortDock & pd = get<PortDock>();
- pd.m_warehouse = &mol().get<Warehouse>(m_warehouse);
-
- pd.m_waiting.resize(m_waiting.size());
- for (uint32_t i = 0; i < m_waiting.size(); ++i) {
- pd.m_waiting[i] = m_waiting[i].get(mol());
- }
-}
-
-void PortDock::Loader::load_finish()
-{
- PlayerImmovable::Loader::load_finish();
-
- PortDock & pd = get<PortDock>();
-
- if (pd.m_warehouse->get_portdock() != &pd) {
- log("Inconsistent PortDock <> Warehouse link\n");
- if (upcast(Game, game, &egbase()))
- pd.schedule_destroy(*game);
- }
-
- // This shouldn't be necessary, but let's check just in case
- if (!pd.m_fleet)
- pd.init_fleet(egbase());
-}
-
-Map_Object::Loader * PortDock::load
- (Editor_Game_Base & egbase, Map_Map_Object_Loader & mol, FileRead & fr)
-{
- std::auto_ptr<Loader> loader(new Loader);
-
- try {
- // The header has been peeled away by the caller
-
- uint8_t const version = fr.Unsigned8();
- if (1 <= version && version <= PORTDOCK_SAVEGAME_VERSION) {
- loader->init(egbase, mol, *new PortDock);
- loader->load(fr, version);
- } else
- throw game_data_error(_("unknown/unhandled version %u"), version);
- } catch (const std::exception & e) {
- throw wexception(_("loading portdock: %s"), e.what());
- }
-
- return loader.release();
-}
-
-void PortDock::save(Editor_Game_Base & egbase, Map_Map_Object_Saver & mos, FileWrite & fw)
-{
- fw.Unsigned8(header_PortDock);
- fw.Unsigned8(PORTDOCK_SAVEGAME_VERSION);
-
- PlayerImmovable::save(egbase, mos, fw);
-
- fw.Unsigned32(mos.get_object_file_index(*m_warehouse));
- fw.Unsigned16(m_dockpoints.size());
- container_iterate_const(PositionList, m_dockpoints, it) {
- fw.Coords32(*it);
- }
-
- fw.Unsigned8(m_need_ship);
-
- fw.Unsigned32(m_waiting.size());
- container_iterate(std::vector<ShippingItem>, m_waiting, it) {
- it->save(egbase, mos, fw);
- }
-}
-
-} // namespace Widelands
+PortDock::Loader::Loader() : m_warehouse(0) {}
+
+void PortDock::Loader::load(FileRead& fr, uint8_t version) {
+ PlayerImmovable::Loader::load(fr);
+
+ PortDock& pd = get<PortDock>();
+
+ m_warehouse = fr.Unsigned32();
+ uint16_t nrdockpoints = fr.Unsigned16();
+
+ pd.m_dockpoints.resize(nrdockpoints);
+ for (uint16_t i = 0; i < nrdockpoints; ++i) {
+ pd.m_dockpoints[i] = fr.Coords32(egbase().map().extent());
+ pd.set_position(egbase(), pd.m_dockpoints[i]);
+ }
+
+ if (version >= 2) {
+ pd.m_need_ship = fr.Unsigned8();
+
+ m_waiting.resize(fr.Unsigned32());
+ container_iterate(std::vector<ShippingItem::Loader>, m_waiting, it) { it->load(fr); }
+ }
+}
+
+void PortDock::Loader::load_pointers() {
+ PlayerImmovable::Loader::load_pointers();
+
+ PortDock& pd = get<PortDock>();
+ pd.m_warehouse = &mol().get<Warehouse>(m_warehouse);
+
+ pd.m_waiting.resize(m_waiting.size());
+ for (uint32_t i = 0; i < m_waiting.size(); ++i) {
+ pd.m_waiting[i] = m_waiting[i].get(mol());
+ }
+}
+
+void PortDock::Loader::load_finish() {
+ PlayerImmovable::Loader::load_finish();
+
+ PortDock& pd = get<PortDock>();
+
+ if (pd.m_warehouse->get_portdock() != &pd) {
+ log("Inconsistent PortDock <> Warehouse link\n");
+ if (upcast(Game, game, &egbase()))
+ pd.schedule_destroy(*game);
+ }
+
+ // This shouldn't be necessary, but let's check just in case
+ if (!pd.m_fleet)
+ pd.init_fleet(egbase());
+}
+
+Map_Object::Loader* PortDock::load(Editor_Game_Base& egbase,
+ Map_Map_Object_Loader& mol,
+ FileRead& fr) {
+ std::auto_ptr<Loader> loader(new Loader);
+
+ try {
+ // The header has been peeled away by the caller
+
+ uint8_t const version = fr.Unsigned8();
+ if (1 <= version && version <= PORTDOCK_SAVEGAME_VERSION) {
+ loader->init(egbase, mol, *new PortDock);
+ loader->load(fr, version);
+ } else
+ throw game_data_error(_("unknown/unhandled version %u"), version);
+ }
+ catch (const std::exception & e) {
+ throw wexception(_("loading portdock: %s"), e.what());
+ }
+
+ return loader.release();
+}
+
+void PortDock::save(Editor_Game_Base& egbase, Map_Map_Object_Saver& mos, FileWrite& fw) {
+ fw.Unsigned8(header_PortDock);
+ fw.Unsigned8(PORTDOCK_SAVEGAME_VERSION);
+
+ PlayerImmovable::save(egbase, mos, fw);
+
+ fw.Unsigned32(mos.get_object_file_index(*m_warehouse));
+ fw.Unsigned16(m_dockpoints.size());
+ container_iterate_const(PositionList, m_dockpoints, it) { fw.Coords32(*it); }
+
+ fw.Unsigned8(m_need_ship);
+
+ fw.Unsigned32(m_waiting.size());
+ container_iterate(std::vector<ShippingItem>, m_waiting, it) { it->save(egbase, mos, fw); }
+}
+
+} // namespace Widelands
=== modified file 'src/economy/portdock.h'
--- src/economy/portdock.h 2013-02-10 19:36:24 +0000
+++ src/economy/portdock.h 2013-05-18 05:56:27 +0000
@@ -58,83 +58,80 @@
* implemented at the moment.
*/
struct PortDock : PlayerImmovable {
- PortDock();
-
- void add_position(Widelands::Coords where);
- void set_warehouse(Warehouse * wh);
- Warehouse * get_warehouse() const {return m_warehouse;}
-
- Fleet * get_fleet() const {return m_fleet;}
- PortDock * get_dock(Flag & flag) const;
- bool get_need_ship() const {return m_need_ship;}
-
- virtual void set_economy(Economy *);
-
- virtual int32_t get_size() const throw ();
- virtual bool get_passable() const throw ();
- virtual int32_t get_type() const throw ();
- virtual char const * type_name() const throw ();
-
- virtual Flag & base_flag();
- virtual PositionList get_positions
- (const Editor_Game_Base &) const throw ();
- virtual void draw
- (const Editor_Game_Base &, RenderTarget &, const FCoords, const Point);
- virtual const std::string & name() const throw ();
-
- virtual void init(Editor_Game_Base &);
- virtual void cleanup(Editor_Game_Base &);
-
- void add_neighbours(std::vector<RoutingNodeNeighbour> & neighbours);
-
- void add_shippingitem(Game &, WareInstance &);
- void update_shippingitem(Game &, WareInstance &);
-
- void add_shippingitem(Game &, Worker &);
- void update_shippingitem(Game &, Worker &);
-
- void ship_arrived(Game &, Ship &);
-
- virtual void log_general_info(const Editor_Game_Base &);
-
- uint32_t count_waiting(WareWorker waretype, Ware_Index wareindex);
-
-private:
- friend struct Fleet;
-
- void init_fleet(Editor_Game_Base & egbase);
- void set_fleet(Fleet * fleet);
- void _update_shippingitem(Game &, std::vector<ShippingItem>::iterator);
- void set_need_ship(Game &, bool need);
-
- Fleet * m_fleet;
- Warehouse * m_warehouse;
- PositionList m_dockpoints;
- std::vector<ShippingItem> m_waiting;
- bool m_need_ship;
-
- // saving and loading
-protected:
- struct Loader : PlayerImmovable::Loader {
- Loader();
-
- void load(FileRead &, uint8_t version);
- virtual void load_pointers();
- virtual void load_finish();
-
- private:
- uint32_t m_warehouse;
- std::vector<ShippingItem::Loader> m_waiting;
- };
-
-public:
- virtual bool has_new_save_support() {return true;}
- virtual void save(Editor_Game_Base &, Map_Map_Object_Saver &, FileWrite &);
-
- static Map_Object::Loader * load
- (Editor_Game_Base &, Map_Map_Object_Loader &, FileRead &);
+ PortDock();
+
+ void add_position(Widelands::Coords where);
+ void set_warehouse(Warehouse* wh);
+ Warehouse* get_warehouse() const { return m_warehouse; }
+
+ Fleet* get_fleet() const { return m_fleet; }
+ PortDock* get_dock(Flag& flag) const;
+ bool get_need_ship() const { return m_need_ship; }
+
+ virtual void set_economy(Economy*);
+
+ virtual int32_t get_size() const throw();
+ virtual bool get_passable() const throw();
+ virtual int32_t get_type() const throw();
+ virtual char const* type_name() const throw();
+
+ virtual Flag& base_flag();
+ virtual PositionList get_positions(const Editor_Game_Base&) const throw();
+ virtual void draw(const Editor_Game_Base&, RenderTarget&, const FCoords&, const Point&);
+ virtual const std::string& name() const throw();
+
+ virtual void init(Editor_Game_Base&);
+ virtual void cleanup(Editor_Game_Base&);
+
+ void add_neighbours(std::vector<RoutingNodeNeighbour>& neighbours);
+
+ void add_shippingitem(Game&, WareInstance&);
+ void update_shippingitem(Game&, WareInstance&);
+
+ void add_shippingitem(Game&, Worker&);
+ void update_shippingitem(Game&, Worker&);
+
+ void ship_arrived(Game&, Ship&);
+
+ virtual void log_general_info(const Editor_Game_Base&);
+
+ uint32_t count_waiting(WareWorker waretype, Ware_Index wareindex);
+
+ private:
+ friend struct Fleet;
+
+ void init_fleet(Editor_Game_Base& egbase);
+ void set_fleet(Fleet* fleet);
+ void _update_shippingitem(Game&, std::vector<ShippingItem>::iterator);
+ void set_need_ship(Game&, bool need);
+
+ Fleet* m_fleet;
+ Warehouse* m_warehouse;
+ PositionList m_dockpoints;
+ std::vector<ShippingItem> m_waiting;
+ bool m_need_ship;
+
+ // saving and loading
+ protected:
+ struct Loader : PlayerImmovable::Loader {
+ Loader();
+
+ void load(FileRead&, uint8_t version);
+ virtual void load_pointers();
+ virtual void load_finish();
+
+ private:
+ uint32_t m_warehouse;
+ std::vector<ShippingItem::Loader> m_waiting;
+ };
+
+ public:
+ virtual bool has_new_save_support() { return true; }
+ virtual void save(Editor_Game_Base&, Map_Map_Object_Saver&, FileWrite&);
+
+ static Map_Object::Loader* load(Editor_Game_Base&, Map_Map_Object_Loader&, FileRead&);
};
-} // namespace Widelands
+} // namespace Widelands
-#endif // ECONOMY_PORTDOCK_H
+#endif // ECONOMY_PORTDOCK_H
=== modified file 'src/economy/request.cc'
--- src/economy/request.cc 2013-04-22 20:15:00 +0000
+++ src/economy/request.cc 2013-05-18 05:56:27 +0000
@@ -37,7 +37,6 @@
#include "logic/warehouse.h"
#include "logic/worker.h"
-
namespace Widelands {
/*
@@ -48,50 +47,46 @@
==============================================================================
*/
-Request::Request
- (PlayerImmovable & _target,
- Ware_Index const index,
- callback_t const cbfn,
- WareWorker const w)
- :
- m_type (w),
- m_target (_target),
- m_target_building (dynamic_cast<Building *>(&_target)),
- m_target_productionsite (dynamic_cast<ProductionSite *>(&_target)),
- m_target_warehouse (dynamic_cast<Warehouse *>(&_target)),
- m_target_constructionsite (dynamic_cast<ConstructionSite *>(&_target)),
- m_economy (_target.get_economy()),
- m_index (index),
- m_count (1),
- m_callbackfn (cbfn),
- m_required_time (_target.owner().egbase().get_gametime()),
- m_required_interval(0),
- m_last_request_time(m_required_time)
-{
- assert(m_type == wwWARE or m_type == wwWORKER);
- if (w == wwWARE and _target.owner().tribe().get_nrwares() <= index)
- throw wexception
- ("creating ware request with index %u, but tribe has only %u "
- "ware types",
- index.value(), _target.owner().tribe().get_nrwares ().value());
- if (w == wwWORKER and _target.owner().tribe().get_nrworkers() <= index)
- throw wexception
- ("creating worker request with index %u, but tribe has only %u "
- "worker types",
- index.value(), _target.owner().tribe().get_nrworkers().value());
- if (m_economy)
- m_economy->add_request(*this);
+Request::Request(PlayerImmovable& _target,
+ Ware_Index const index,
+ callback_t const cbfn,
+ WareWorker const w)
+ : m_type(w),
+ m_target(_target),
+ m_target_building(dynamic_cast<Building*>(&_target)),
+ m_target_productionsite(dynamic_cast<ProductionSite*>(&_target)),
+ m_target_warehouse(dynamic_cast<Warehouse*>(&_target)),
+ m_target_constructionsite(dynamic_cast<ConstructionSite*>(&_target)),
+ m_economy(_target.get_economy()),
+ m_index(index),
+ m_count(1),
+ m_callbackfn(cbfn),
+ m_required_time(_target.owner().egbase().get_gametime()),
+ m_required_interval(0),
+ m_last_request_time(m_required_time) {
+ assert(m_type == wwWARE or m_type == wwWORKER);
+ if (w == wwWARE and _target.owner().tribe().get_nrwares() <= index)
+ throw wexception("creating ware request with index %u, but tribe has only %u "
+ "ware types",
+ index.value(),
+ _target.owner().tribe().get_nrwares().value());
+ if (w == wwWORKER and _target.owner().tribe().get_nrworkers() <= index)
+ throw wexception("creating worker request with index %u, but tribe has only %u "
+ "worker types",
+ index.value(),
+ _target.owner().tribe().get_nrworkers().value());
+ if (m_economy)
+ m_economy->add_request(*this);
}
-Request::~Request()
-{
- // Remove from the economy
- if (is_open() and m_economy)
- m_economy->remove_request(*this);
+Request::~Request() {
+ // Remove from the economy
+ if (is_open() and m_economy)
+ m_economy->remove_request(*this);
- // Cancel all ongoing transfers
- while (m_transfers.size())
- cancel_transfer(0);
+ // Cancel all ongoing transfers
+ while (m_transfers.size())
+ cancel_transfer(0);
}
// Modified to allow Requirements and SoldierRequests
@@ -105,223 +100,205 @@
* might have been initialized. We have to kill them and replace
* them through the data in the file
*/
-void Request::Read
- (FileRead & fr, Game & game, Map_Map_Object_Loader & mol)
-{
- try {
- bool fudged_type = false;
- uint16_t const version = fr.Unsigned16();
- if (2 <= version and version <= REQUEST_VERSION) {
- const Tribe_Descr & tribe = m_target.owner().tribe();
- if (version <= 3) {
- // Unfortunately, old versions wrote the index. The best thing
- // that we can do with that is to look it up in a table.
- WareWorker newtype = static_cast<WareWorker>(fr.Unsigned8());
- if (newtype != wwWARE and newtype != wwWORKER)
- throw wexception
- ("type is %u but must be %u (ware) or %u (worker)",
- m_type, wwWARE, wwWORKER);
- uint32_t const legacy_index = fr.Unsigned32();
- if (newtype == wwWORKER) {
- m_type = wwWORKER;
- m_index = Legacy::worker_index
- (tribe,
- m_target.descr().descname(),
- "requests",
- legacy_index);
- } else {
- Ware_Index newindex = Legacy::ware_index
- (tribe,
- m_target.descr().descname(),
- "requests",
- legacy_index);
- if (newindex) {
- m_type = wwWARE;
- m_index = newindex;
- } else {
- log("Request::Read: Legacy ware no longer exists, sticking with default\n");
- fudged_type = true;
- }
- }
- } else {
- char const * const type_name = fr.CString();
- if (Ware_Index const wai = tribe.ware_index(type_name)) {
- m_type = wwWARE;
- m_index = wai;
- } else if (Ware_Index const woi = tribe.worker_index(type_name)) {
- m_type = wwWORKER;
- m_index = woi;
- } else {
- log
- ("Request::Read: unknown type '%s', stick with default %i/%i\n",
- type_name, m_type, m_index.value());
- fudged_type = true;
- }
- }
- if (version <= 5)
- fr.Unsigned8(); // was m_idle
- m_count = fr.Unsigned32();
- m_required_time = fr.Unsigned32();
- m_required_interval = fr.Unsigned32();
-
- if (3 <= version)
- m_last_request_time = fr.Unsigned32();
-
- assert(m_transfers.empty());
-
- uint16_t const nr_transfers = fr.Unsigned16();
- for (uint16_t i = 0; i < nr_transfers; ++i)
- try {
- if (version >= 6) {
- Map_Object * obj = &mol.get<Map_Object>(fr.Unsigned32());
- Transfer * transfer;
-
- if (upcast(Worker, worker, obj)) {
- transfer = worker->get_transfer();
- if (m_type != wwWORKER || !worker->descr().can_act_as(m_index)) {
- log("Request::Read: incompatible transfer type\n");
- if (!fudged_type)
- throw wexception
- ("Request::Read: incompatible transfer type");
- transfer->has_failed();
- transfer = 0;
- }
- } else if (upcast(WareInstance, ware, obj)) {
- transfer = ware->get_transfer();
- if (m_type != wwWARE || ware->descr_index() != m_index) {
- log("Request::Read: incompatible transfer type\n");
- if (!fudged_type)
- throw wexception
- ("Request::Read: incompatible transfer type");
- transfer->has_failed();
- transfer = 0;
- }
- } else
- throw wexception
- ("transfer target %u is neither ware nor worker",
- obj->serial());
-
- if (!transfer) {
- log
- ("WARNING: loading request, transferred object "
- "%u has no transfer\n",
- obj->serial());
- } else {
- transfer->set_request(this);
- m_transfers.push_back(transfer);
- }
- } else {
- uint8_t const what_is = fr.Unsigned8();
- if (what_is != wwWARE and what_is != wwWORKER and what_is != 2)
- throw wexception
- ("type is %u but must be one of {%u (WARE), %u "
- "(WORKER), %u (SOLDIER)}",
- what_is, wwWARE, wwWORKER, 2);
- uint32_t const reg = fr.Unsigned32();
- if (not mol.is_object_known(reg))
- throw wexception("%u is not known", reg);
- Transfer * const trans =
- what_is == wwWARE ?
- new Transfer(game, *this, mol.get<WareInstance>(reg)) :
- new Transfer(game, *this, mol.get<Worker> (reg));
- fr.Unsigned8(); // was: is_idle
- m_transfers.push_back(trans);
-
- if (version < 5)
- if (fr.Unsigned8())
- m_requirements.Read (fr, game, mol);
- }
- } catch (const _wexception & e) {
- throw wexception("transfer %u: %s", i, e.what());
- }
- if (version >= 5)
- m_requirements.Read (fr, game, mol);
- if (!is_open() && m_economy)
- m_economy->remove_request(*this);
- } else
- throw game_data_error(_("unknown/unhandled version %u"), version);
- } catch (const _wexception & e) {
- throw wexception("request: %s", e.what());
- }
+void Request::Read(FileRead& fr, Game& game, Map_Map_Object_Loader& mol) {
+ try {
+ bool fudged_type = false;
+ uint16_t const version = fr.Unsigned16();
+ if (2 <= version and version <= REQUEST_VERSION) {
+ const Tribe_Descr& tribe = m_target.owner().tribe();
+ if (version <= 3) {
+ // Unfortunately, old versions wrote the index. The best thing
+ // that we can do with that is to look it up in a table.
+ WareWorker newtype = static_cast<WareWorker>(fr.Unsigned8());
+ if (newtype != wwWARE and newtype != wwWORKER)
+ throw wexception(
+ "type is %u but must be %u (ware) or %u (worker)", m_type, wwWARE, wwWORKER);
+ uint32_t const legacy_index = fr.Unsigned32();
+ if (newtype == wwWORKER) {
+ m_type = wwWORKER;
+ m_index = Legacy::worker_index(
+ tribe, m_target.descr().descname(), "requests", legacy_index);
+ } else {
+ Ware_Index newindex =
+ Legacy::ware_index(tribe, m_target.descr().descname(), "requests", legacy_index);
+ if (newindex) {
+ m_type = wwWARE;
+ m_index = newindex;
+ } else {
+ log("Request::Read: Legacy ware no longer exists, sticking with default\n");
+ fudged_type = true;
+ }
+ }
+ } else {
+ char const* const type_name = fr.CString();
+ if (Ware_Index const wai = tribe.ware_index(type_name)) {
+ m_type = wwWARE;
+ m_index = wai;
+ } else if (Ware_Index const woi = tribe.worker_index(type_name)) {
+ m_type = wwWORKER;
+ m_index = woi;
+ } else {
+ log("Request::Read: unknown type '%s', stick with default %i/%i\n",
+ type_name,
+ m_type,
+ m_index.value());
+ fudged_type = true;
+ }
+ }
+ if (version <= 5)
+ fr.Unsigned8(); // was m_idle
+ m_count = fr.Unsigned32();
+ m_required_time = fr.Unsigned32();
+ m_required_interval = fr.Unsigned32();
+
+ if (3 <= version)
+ m_last_request_time = fr.Unsigned32();
+
+ assert(m_transfers.empty());
+
+ uint16_t const nr_transfers = fr.Unsigned16();
+ for (uint16_t i = 0; i < nr_transfers; ++i)
+ try {
+ if (version >= 6) {
+ Map_Object* obj = &mol.get<Map_Object>(fr.Unsigned32());
+ Transfer* transfer;
+
+ if (upcast(Worker, worker, obj)) {
+ transfer = worker->get_transfer();
+ if (m_type != wwWORKER || !worker->descr().can_act_as(m_index)) {
+ log("Request::Read: incompatible transfer type\n");
+ if (!fudged_type)
+ throw wexception("Request::Read: incompatible transfer type");
+ transfer->has_failed();
+ transfer = 0;
+ }
+ } else if (upcast(WareInstance, ware, obj)) {
+ transfer = ware->get_transfer();
+ if (m_type != wwWARE || ware->descr_index() != m_index) {
+ log("Request::Read: incompatible transfer type\n");
+ if (!fudged_type)
+ throw wexception("Request::Read: incompatible transfer type");
+ transfer->has_failed();
+ transfer = 0;
+ }
+ } else
+ throw wexception("transfer target %u is neither ware nor worker",
+ obj->serial());
+
+ if (!transfer) {
+ log("WARNING: loading request, transferred object "
+ "%u has no transfer\n",
+ obj->serial());
+ } else {
+ transfer->set_request(this);
+ m_transfers.push_back(transfer);
+ }
+ } else {
+ uint8_t const what_is = fr.Unsigned8();
+ if (what_is != wwWARE and what_is != wwWORKER and what_is != 2)
+ throw wexception("type is %u but must be one of {%u (WARE), %u "
+ "(WORKER), %u (SOLDIER)}",
+ what_is,
+ wwWARE,
+ wwWORKER,
+ 2);
+ uint32_t const reg = fr.Unsigned32();
+ if (not mol.is_object_known(reg))
+ throw wexception("%u is not known", reg);
+ Transfer* const trans =
+ what_is == wwWARE ? new Transfer(game, *this, mol.get<WareInstance>(reg))
+ : new Transfer(game, *this, mol.get<Worker>(reg));
+ fr.Unsigned8(); // was: is_idle
+ m_transfers.push_back(trans);
+
+ if (version < 5)
+ if (fr.Unsigned8())
+ m_requirements.Read(fr, game, mol);
+ }
+ }
+ catch (const _wexception & e) {
+ throw wexception("transfer %u: %s", i, e.what());
+ }
+ if (version >= 5)
+ m_requirements.Read(fr, game, mol);
+ if (!is_open() && m_economy)
+ m_economy->remove_request(*this);
+ } else
+ throw game_data_error(_("unknown/unhandled version %u"), version);
+ }
+ catch (const _wexception & e) {
+ throw wexception("request: %s", e.what());
+ }
}
/**
* Write this request to a file
*/
-void Request::Write
- (FileWrite & fw, Game & game, Map_Map_Object_Saver & mos) const
-{
- fw.Unsigned16(REQUEST_VERSION);
-
- // Target and econmy should be set. Same is true for callback stuff.
-
- assert(m_type == wwWARE or m_type == wwWORKER);
- const Tribe_Descr & tribe = m_target.owner().tribe();
- assert(m_type != wwWARE or m_index < tribe.get_nrwares ());
- assert(m_type != wwWORKER or m_index < tribe.get_nrworkers());
- fw.CString
- (m_type == wwWARE ?
- tribe.get_ware_descr (m_index)->name() :
- tribe.get_worker_descr(m_index)->name());
-
- fw.Unsigned32(m_count);
-
- fw.Unsigned32(m_required_time);
- fw.Unsigned32(m_required_interval);
-
- fw.Unsigned32(m_last_request_time);
-
- fw.Unsigned16(m_transfers.size()); // Write number of current transfers.
- for (uint32_t i = 0; i < m_transfers.size(); ++i) {
- Transfer & trans = *m_transfers[i];
- if (trans.m_item) { // write ware/worker
- assert(mos.is_object_known(*trans.m_item));
- fw.Unsigned32(mos.get_object_file_index(*trans.m_item));
- } else if (trans.m_worker) {
- assert(mos.is_object_known(*trans.m_worker));
- fw.Unsigned32(mos.get_object_file_index(*trans.m_worker));
- }
- }
- m_requirements.Write (fw, game, mos);
+void Request::Write(FileWrite& fw, Game& game, Map_Map_Object_Saver& mos) const {
+ fw.Unsigned16(REQUEST_VERSION);
+
+ // Target and econmy should be set. Same is true for callback stuff.
+
+ assert(m_type == wwWARE or m_type == wwWORKER);
+ const Tribe_Descr& tribe = m_target.owner().tribe();
+ assert(m_type != wwWARE or m_index < tribe.get_nrwares());
+ assert(m_type != wwWORKER or m_index < tribe.get_nrworkers());
+ fw.CString(m_type == wwWARE ? tribe.get_ware_descr(m_index)->name()
+ : tribe.get_worker_descr(m_index)->name());
+
+ fw.Unsigned32(m_count);
+
+ fw.Unsigned32(m_required_time);
+ fw.Unsigned32(m_required_interval);
+
+ fw.Unsigned32(m_last_request_time);
+
+ fw.Unsigned16(m_transfers.size()); // Write number of current transfers.
+ for (uint32_t i = 0; i < m_transfers.size(); ++i) {
+ Transfer& trans = *m_transfers[i];
+ if (trans.m_item) { // write ware/worker
+ assert(mos.is_object_known(*trans.m_item));
+ fw.Unsigned32(mos.get_object_file_index(*trans.m_item));
+ } else if (trans.m_worker) {
+ assert(mos.is_object_known(*trans.m_worker));
+ fw.Unsigned32(mos.get_object_file_index(*trans.m_worker));
+ }
+ }
+ m_requirements.Write(fw, game, mos);
}
/**
* Figure out the flag we need to deliver to.
*/
-Flag & Request::target_flag() const
-{
- return target().base_flag();
-}
+Flag& Request::target_flag() const { return target().base_flag(); }
/**
* Return the point in time at which we want the item of the given number to
* be delivered. nr is in the range [0..m_count[
*/
-int32_t Request::get_base_required_time
- (Editor_Game_Base & egbase, uint32_t const nr) const
-{
- if (m_count <= nr) {
- if (not(m_count == 1 and nr == 1)) {
- log
- ("Request::get_base_required_time: WARNING nr = %u but count is %u, "
- "which is not allowed according to the comment for this function\n",
- nr, m_count);
- }
- }
- int32_t const curtime = egbase.get_gametime();
-
- if (!nr || !m_required_interval)
- return m_required_time;
-
- if ((curtime - m_required_time) > (m_required_interval * 2)) {
- if (nr == 1)
- return m_required_time + (curtime - m_required_time) / 2;
-
- assert(2 <= nr);
- return curtime + (nr - 2) * m_required_interval;
- }
-
- return m_required_time + nr * m_required_interval;
+int32_t Request::get_base_required_time(Editor_Game_Base& egbase, uint32_t const nr) const {
+ if (m_count <= nr) {
+ if (not(m_count == 1 and nr == 1)) {
+ log("Request::get_base_required_time: WARNING nr = %u but count is %u, "
+ "which is not allowed according to the comment for this function\n",
+ nr,
+ m_count);
+ }
+ }
+ int32_t const curtime = egbase.get_gametime();
+
+ if (!nr || !m_required_interval)
+ return m_required_time;
+
+ if ((curtime - m_required_time) > (m_required_interval * 2)) {
+ if (nr == 1)
+ return m_required_time + (curtime - m_required_time) / 2;
+
+ assert(2 <= nr);
+ return curtime + (nr - 2) * m_required_interval;
+ }
+
+ return m_required_time + nr * m_required_interval;
}
/**
@@ -329,178 +306,153 @@
* Can be in the past, indicating that we have been idling, waiting for the
* ware.
*/
-int32_t Request::get_required_time() const
-{
- return
- get_base_required_time(m_economy->owner().egbase(), m_transfers.size());
+int32_t Request::get_required_time() const {
+ return get_base_required_time(m_economy->owner().egbase(), m_transfers.size());
}
//#define MAX_IDLE_PRIORITY 100
-#define PRIORITY_MAX_COST 50000
-#define COST_WEIGHT_IN_PRIORITY 1
-#define WAITTIME_WEIGHT_IN_PRIORITY 2
+#define PRIORITY_MAX_COST 50000
+#define COST_WEIGHT_IN_PRIORITY 1
+#define WAITTIME_WEIGHT_IN_PRIORITY 2
/**
* Return the request priority used to sort requests or -1 to skip request
*/
-int32_t Request::get_priority (int32_t cost) const
-{
- int MAX_IDLE_PRIORITY = 100;
- bool is_construction_site = false;
- int32_t modifier = DEFAULT_PRIORITY;
-
- if (m_target_building) {
- if (m_target_productionsite && m_target_productionsite->is_stopped())
- return -1;
-
- modifier = m_target_building->get_priority(get_type(), get_index());
- if (m_target_constructionsite)
- is_construction_site = true;
- else if (m_target_warehouse)
- // if warehouse calculated a priority use it
- // else lower priority based on cost
- return
- modifier != 100 ? modifier :
- std::max
- (1,
- MAX_IDLE_PRIORITY
- -
- cost * MAX_IDLE_PRIORITY / PRIORITY_MAX_COST);
- }
-
- if (cost > PRIORITY_MAX_COST)
- cost = PRIORITY_MAX_COST;
-
- // priority is higher if building waits for ware a long time
- // additional factor - cost to deliver, so nearer building
- // with same priority will get ware first
- // make sure that idle request are lower
- return
- MAX_IDLE_PRIORITY
- +
- std::max
- (1,
- ((m_economy->owner().egbase().get_gametime() -
- (is_construction_site ?
- get_required_time() : get_last_request_time()))
- *
- WAITTIME_WEIGHT_IN_PRIORITY
- +
- (PRIORITY_MAX_COST - cost) * COST_WEIGHT_IN_PRIORITY)
- *
- modifier);
+int32_t Request::get_priority(int32_t cost) const {
+ int MAX_IDLE_PRIORITY = 100;
+ bool is_construction_site = false;
+ int32_t modifier = DEFAULT_PRIORITY;
+
+ if (m_target_building) {
+ if (m_target_productionsite && m_target_productionsite->is_stopped())
+ return -1;
+
+ modifier = m_target_building->get_priority(get_type(), get_index());
+ if (m_target_constructionsite)
+ is_construction_site = true;
+ else if (m_target_warehouse)
+ // if warehouse calculated a priority use it
+ // else lower priority based on cost
+ return modifier != 100
+ ? modifier
+ : std::max(1, MAX_IDLE_PRIORITY - cost * MAX_IDLE_PRIORITY / PRIORITY_MAX_COST);
+ }
+
+ if (cost > PRIORITY_MAX_COST)
+ cost = PRIORITY_MAX_COST;
+
+ // priority is higher if building waits for ware a long time
+ // additional factor - cost to deliver, so nearer building
+ // with same priority will get ware first
+ // make sure that idle request are lower
+ return MAX_IDLE_PRIORITY +
+ std::max(1,
+ ((m_economy->owner().egbase().get_gametime() -
+ (is_construction_site ? get_required_time() : get_last_request_time())) *
+ WAITTIME_WEIGHT_IN_PRIORITY +
+ (PRIORITY_MAX_COST - cost) * COST_WEIGHT_IN_PRIORITY) *
+ modifier);
}
-
/**
* Return the transfer priority, based on the priority set at the destination
*/
-uint32_t Request::get_transfer_priority() const
-{
- uint32_t pri = 0;
-
- if (m_target_building) {
- if (m_target_productionsite && m_target_productionsite->is_stopped())
- return 0;
-
- pri = m_target_building->get_priority(get_type(), get_index());
- if (m_target_constructionsite)
- return pri + 3;
- else if (m_target_warehouse)
- return pri - 2;
- }
- return pri;
+uint32_t Request::get_transfer_priority() const {
+ uint32_t pri = 0;
+
+ if (m_target_building) {
+ if (m_target_productionsite && m_target_productionsite->is_stopped())
+ return 0;
+
+ pri = m_target_building->get_priority(get_type(), get_index());
+ if (m_target_constructionsite)
+ return pri + 3;
+ else if (m_target_warehouse)
+ return pri - 2;
+ }
+ return pri;
}
/**
* Change the Economy we belong to.
*/
-void Request::set_economy(Economy * const e)
-{
- if (m_economy != e) {
- if (m_economy && is_open())
- m_economy->remove_request(*this);
- m_economy = e;
- if (m_economy && is_open())
- m_economy-> add_request(*this);
- }
+void Request::set_economy(Economy* const e) {
+ if (m_economy != e) {
+ if (m_economy && is_open())
+ m_economy->remove_request(*this);
+ m_economy = e;
+ if (m_economy && is_open())
+ m_economy->add_request(*this);
+ }
}
/**
* Change the number of wares we need.
*/
-void Request::set_count(uint32_t const count)
-{
- bool const wasopen = is_open();
-
- m_count = count;
-
- // Cancel unneeded transfers. This should be more clever about which
- // transfers to cancel. Then again, this loop shouldn't execute during
- // normal play anyway
- while (m_count < m_transfers.size())
- cancel_transfer(m_transfers.size() - 1);
-
- // Update the economy
- if (m_economy) {
- if (wasopen && !is_open())
- m_economy->remove_request(*this);
- else if (!wasopen && is_open())
- m_economy->add_request(*this);
- }
+void Request::set_count(uint32_t const count) {
+ bool const wasopen = is_open();
+
+ m_count = count;
+
+ // Cancel unneeded transfers. This should be more clever about which
+ // transfers to cancel. Then again, this loop shouldn't execute during
+ // normal play anyway
+ while (m_count < m_transfers.size())
+ cancel_transfer(m_transfers.size() - 1);
+
+ // Update the economy
+ if (m_economy) {
+ if (wasopen && !is_open())
+ m_economy->remove_request(*this);
+ else if (!wasopen && is_open())
+ m_economy->add_request(*this);
+ }
}
/**
* Change the time at which the first item to be delivered is needed.
* Default is the gametime of the Request creation.
*/
-void Request::set_required_time(int32_t const time)
-{
- m_required_time = time;
-}
+void Request::set_required_time(int32_t const time) { m_required_time = time; }
/**
* Change the time between desired delivery of items.
*/
-void Request::set_required_interval(int32_t const interval)
-{
- m_required_interval = interval;
-}
+void Request::set_required_interval(int32_t const interval) { m_required_interval = interval; }
/**
* Begin transfer of the requested ware from the given supply.
* This function does not take ownership of route, i.e. the caller is
* responsible for its deletion.
*/
-void Request::start_transfer(Game & game, Supply & supp)
-{
- assert(is_open());
-
- ::StreamWrite & ss = game.syncstream();
- ss.Unsigned32(0x01decafa); // appears as facade01 in sync stream
- ss.Unsigned32(target().serial());
- ss.Unsigned32(supp.get_position(game)->serial());
-
- Transfer * t;
- if (get_type() == wwWORKER) {
- // Begin the transfer of a soldier or worker.
- // launch_worker() creates or starts the worker
- Worker & s = supp.launch_worker(game, *this);
- ss.Unsigned32(s.serial());
- t = new Transfer(game, *this, s);
- } else {
- // Begin the transfer of an item. The item itself is passive.
- // launch_item() ensures the WareInstance is transported out of the
- // warehouse. Once it's on the flag, the flag code will decide what to
- // do with it.
- WareInstance & item = supp.launch_item(game, *this);
- ss.Unsigned32(item.serial());
- t = new Transfer(game, *this, item);
- }
-
- m_transfers.push_back(t);
- if (!is_open())
- m_economy->remove_request(*this);
+void Request::start_transfer(Game& game, Supply& supp) {
+ assert(is_open());
+
+ ::StreamWrite& ss = game.syncstream();
+ ss.Unsigned32(0x01decafa); // appears as facade01 in sync stream
+ ss.Unsigned32(target().serial());
+ ss.Unsigned32(supp.get_position(game)->serial());
+
+ Transfer* t;
+ if (get_type() == wwWORKER) {
+ // Begin the transfer of a soldier or worker.
+ // launch_worker() creates or starts the worker
+ Worker& s = supp.launch_worker(game, *this);
+ ss.Unsigned32(s.serial());
+ t = new Transfer(game, *this, s);
+ } else {
+ // Begin the transfer of an item. The item itself is passive.
+ // launch_item() ensures the WareInstance is transported out of the
+ // warehouse. Once it's on the flag, the flag code will decide what to
+ // do with it.
+ WareInstance& item = supp.launch_item(game, *this);
+ ss.Unsigned32(item.serial());
+ t = new Transfer(game, *this, item);
+ }
+
+ m_transfers.push_back(t);
+ if (!is_open())
+ m_economy->remove_request(*this);
}
/**
@@ -508,25 +460,24 @@
* This will call a callback function in the target, which is then responsible
* for removing and deleting the request.
*/
-void Request::transfer_finish(Game & game, Transfer & t)
-{
- Worker * const w = t.m_worker;
-
- if (t.m_item)
- t.m_item->destroy(game);
-
- t.m_worker = 0;
- t.m_item = 0;
-
- remove_transfer(find_transfer(t));
-
- set_required_time(get_base_required_time(game, 1));
- --m_count;
-
- // the callback functions are likely to delete us,
- // therefore we musn't access member variables behind this
- // point
- (*m_callbackfn)(game, *this, m_index, w, m_target);
+void Request::transfer_finish(Game& game, Transfer& t) {
+ Worker* const w = t.m_worker;
+
+ if (t.m_item)
+ t.m_item->destroy(game);
+
+ t.m_worker = 0;
+ t.m_item = 0;
+
+ remove_transfer(find_transfer(t));
+
+ set_required_time(get_base_required_time(game, 1));
+ --m_count;
+
+ // the callback functions are likely to delete us,
+ // therefore we musn't access member variables behind this
+ // point
+ (*m_callbackfn)(game, *this, m_index, w, m_target);
}
/**
@@ -535,54 +486,48 @@
*
* Re-open the request.
*/
-void Request::transfer_fail(Game &, Transfer & t) {
- bool const wasopen = is_open();
-
- t.m_worker = 0;
- t.m_item = 0;
-
- remove_transfer(find_transfer(t));
-
- if (!wasopen)
- m_economy->add_request(*this);
+void Request::transfer_fail(Game&, Transfer& t) {
+ bool const wasopen = is_open();
+
+ t.m_worker = 0;
+ t.m_item = 0;
+
+ remove_transfer(find_transfer(t));
+
+ if (!wasopen)
+ m_economy->add_request(*this);
}
/// Cancel the transfer with the given index.
///
/// \note This does *not* update whether the \ref Request is registered with
/// the \ref Economy or not.
-void Request::cancel_transfer(uint32_t const idx)
-{
- remove_transfer(idx);
-}
+void Request::cancel_transfer(uint32_t const idx) { remove_transfer(idx); }
/**
* Remove and free the transfer with the given index.
* This does not update the Transfer's worker or item, and it does not update
* whether the Request is registered with the Economy.
*/
-void Request::remove_transfer(uint32_t const idx)
-{
- Transfer * const t = m_transfers[idx];
-
- m_transfers.erase(m_transfers.begin() + idx);
-
- delete t;
+void Request::remove_transfer(uint32_t const idx) {
+ Transfer* const t = m_transfers[idx];
+
+ m_transfers.erase(m_transfers.begin() + idx);
+
+ delete t;
}
/**
* Lookup a \ref Transfer in the transfers array.
* \throw wexception if the \ref Transfer is not registered with us.
*/
-uint32_t Request::find_transfer(Transfer & t)
-{
- TransferList::const_iterator const it =
- std::find(m_transfers.begin(), m_transfers.end(), &t);
-
- if (it == m_transfers.end())
- throw wexception("Request::find_transfer(): not found");
-
- return it - m_transfers.begin();
+uint32_t Request::find_transfer(Transfer& t) {
+ TransferList::const_iterator const it = std::find(m_transfers.begin(), m_transfers.end(), &t);
+
+ if (it == m_transfers.end())
+ throw wexception("Request::find_transfer(): not found");
+
+ return it - m_transfers.begin();
}
}
=== modified file 'src/economy/request.h'
--- src/economy/request.h 2013-04-22 20:15:00 +0000
+++ src/economy/request.h 2013-05-18 05:56:27 +0000
@@ -58,85 +58,86 @@
* The required time has no meaning for idle requests.
*/
struct Request : public Trackable {
- friend class Economy;
- friend class RequestList;
-
- typedef void (*callback_t)
- (Game &, Request &, Ware_Index, Worker *, PlayerImmovable &);
-
- Request(PlayerImmovable & target, Ware_Index, callback_t, WareWorker);
- ~Request();
-
- PlayerImmovable & target() const throw () {return m_target;}
- Ware_Index get_index() const {return m_index;}
- WareWorker get_type() const {return m_type;}
- uint32_t get_count() const {return m_count;}
- uint32_t get_open_count() const {return m_count - m_transfers.size();}
- bool is_open() const {return m_transfers.size() < m_count;}
- Economy * get_economy() const throw () {return m_economy;}
- int32_t get_required_time() const;
- int32_t get_last_request_time() const {return m_last_request_time;}
- int32_t get_priority(int32_t cost) const;
- uint32_t get_transfer_priority() const;
- uint32_t get_num_transfers() const {return m_transfers.size();}
-
- Flag & target_flag() const;
-
- void set_economy(Economy *);
- void set_count(uint32_t);
- void set_required_time(int32_t time);
- void set_required_interval(int32_t interval);
-
- void set_last_request_time(int32_t const time) {m_last_request_time = time;}
-
- void start_transfer(Game &, Supply &);
-
- void Read (FileRead &, Game &, Map_Map_Object_Loader &);
- void Write(FileWrite &, Game &, Map_Map_Object_Saver &) const;
- Worker * get_transfer_worker();
-
- // callbacks for WareInstance/Worker code
- void transfer_finish(Game &, Transfer &);
- void transfer_fail (Game &, Transfer &);
-
- void set_requirements (const Requirements & r) {m_requirements = r;}
- const Requirements & get_requirements () const {return m_requirements;}
-
-private:
- int32_t get_base_required_time(Editor_Game_Base &, uint32_t nr) const;
-public:
- void cancel_transfer(uint32_t idx);
-private:
- void remove_transfer(uint32_t idx);
- uint32_t find_transfer(Transfer &);
-
- typedef std::vector<Transfer *> TransferList;
-
- WareWorker m_type;
-
- PlayerImmovable & m_target; // who requested it?
- // Copies of m_target of various pointer types, to avoid expensive
- // dynamic casting at runtime. Variables with an incompatible type
- // are filled with nulls.
- Building * m_target_building;
- ProductionSite * m_target_productionsite;
- Warehouse * m_target_warehouse;
- ConstructionSite * m_target_constructionsite;
-
- Economy * m_economy;
- Ware_Index m_index; // the index of the ware descr
- uint32_t m_count; // how many do we need in total
-
- callback_t m_callbackfn; // called on request success
-
- // when do we need the first ware (can be in the past)
- int32_t m_required_time;
- int32_t m_required_interval; // time between items
- int32_t m_last_request_time;
-
- TransferList m_transfers; // maximum size is m_count
-
- Requirements m_requirements;
+ friend class Economy;
+ friend class RequestList;
+
+ typedef void (*callback_t)(Game&, Request&, Ware_Index, Worker*, PlayerImmovable&);
+
+ Request(PlayerImmovable& target, Ware_Index, callback_t, WareWorker);
+ ~Request();
+
+ PlayerImmovable& target() const throw() { return m_target; }
+ Ware_Index get_index() const { return m_index; }
+ WareWorker get_type() const { return m_type; }
+ uint32_t get_count() const { return m_count; }
+ uint32_t get_open_count() const { return m_count - m_transfers.size(); }
+ bool is_open() const { return m_transfers.size() < m_count; }
+ Economy* get_economy() const throw() { return m_economy; }
+ int32_t get_required_time() const;
+ int32_t get_last_request_time() const { return m_last_request_time; }
+ int32_t get_priority(int32_t cost) const;
+ uint32_t get_transfer_priority() const;
+ uint32_t get_num_transfers() const { return m_transfers.size(); }
+
+ Flag& target_flag() const;
+
+ void set_economy(Economy*);
+ void set_count(uint32_t);
+ void set_required_time(int32_t time);
+ void set_required_interval(int32_t interval);
+
+ void set_last_request_time(int32_t const time) { m_last_request_time = time; }
+
+ void start_transfer(Game&, Supply&);
+
+ void Read(FileRead&, Game&, Map_Map_Object_Loader&);
+ void Write(FileWrite&, Game&, Map_Map_Object_Saver&) const;
+ Worker* get_transfer_worker();
+
+ // callbacks for WareInstance/Worker code
+ void transfer_finish(Game&, Transfer&);
+ void transfer_fail(Game&, Transfer&);
+
+ void set_requirements(const Requirements& r) { m_requirements = r; }
+ const Requirements& get_requirements() const { return m_requirements; }
+
+ private:
+ int32_t get_base_required_time(Editor_Game_Base&, uint32_t nr) const;
+
+ public:
+ void cancel_transfer(uint32_t idx);
+
+ private:
+ void remove_transfer(uint32_t idx);
+ uint32_t find_transfer(Transfer&);
+
+ typedef std::vector<Transfer*> TransferList;
+
+ WareWorker m_type;
+
+ PlayerImmovable& m_target; // who requested it?
+ // Copies of m_target of various pointer types, to avoid expensive
+ // dynamic casting at runtime. Variables with an incompatible type
+ // are filled with nulls.
+ Building* m_target_building;
+ ProductionSite* m_target_productionsite;
+ Warehouse* m_target_warehouse;
+ ConstructionSite* m_target_constructionsite;
+
+ Economy* m_economy;
+ Ware_Index m_index; // the index of the ware descr
+ uint32_t m_count; // how many do we need in total
+
+ callback_t m_callbackfn; // called on request success
+
+ // when do we need the first ware (can be in the past)
+ int32_t m_required_time;
+ int32_t m_required_interval; // time between items
+ int32_t m_last_request_time;
+
+ TransferList m_transfers; // maximum size is m_count
+
+ Requirements m_requirements;
};
}
=== modified file 'src/economy/road.cc'
--- src/economy/road.cc 2013-02-10 19:36:24 +0000
+++ src/economy/road.cc 2013-05-18 05:56:27 +0000
@@ -38,224 +38,187 @@
// dummy instance because Map_Object needs a description
const Map_Object_Descr g_road_descr("road", "Road");
-bool Road::IsRoadDescr(Map_Object_Descr const * const descr)
-{
- return descr == &g_road_descr;
-}
+bool Road::IsRoadDescr(Map_Object_Descr const* const descr) { return descr == &g_road_descr; }
/**
* Most of the actual work is done in init.
*/
-Road::Road() :
- PlayerImmovable (g_road_descr),
- m_busyness (0),
- m_busyness_last_update(0),
- m_type (0),
- m_idle_index(0)
-{
- m_flags[0] = m_flags[1] = 0;
- m_flagidx[0] = m_flagidx[1] = -1;
+Road::Road()
+ : PlayerImmovable(g_road_descr),
+ m_busyness(0),
+ m_busyness_last_update(0),
+ m_type(0),
+ m_idle_index(0) {
+ m_flags[0] = m_flags[1] = 0;
+ m_flagidx[0] = m_flagidx[1] = -1;
- /*
- * Initialize the worker slots for the road
- * TODO: make this configurable
- */
- CarrierSlot slot;
- m_carrier_slots.push_back(slot);
- m_carrier_slots.push_back(slot);
- m_carrier_slots[0].carrier_type = 1;
- m_carrier_slots[1].carrier_type = 2;
+ /*
+ * Initialize the worker slots for the road
+ * TODO: make this configurable
+ */
+ CarrierSlot slot;
+ m_carrier_slots.push_back(slot);
+ m_carrier_slots.push_back(slot);
+ m_carrier_slots[0].carrier_type = 1;
+ m_carrier_slots[1].carrier_type = 2;
}
-Road::CarrierSlot::CarrierSlot() :
- carrier (0),
- carrier_request(0),
- carrier_type(0)
- {}
-
+Road::CarrierSlot::CarrierSlot() : carrier(0), carrier_request(0), carrier_type(0) {}
/**
* Most of the actual work is done in cleanup.
*/
-Road::~Road()
-{
- container_iterate_const(SlotVector, m_carrier_slots, i)
- delete i.current->carrier_request;
+Road::~Road() {
+ container_iterate_const(SlotVector, m_carrier_slots, i)
+ delete i.current->carrier_request;
}
/**
* Create a road between the given flags, using the given path.
*/
-Road & Road::create
- (Editor_Game_Base & egbase,
- Flag & start, Flag & end, const Path & path)
-{
- assert(start.get_position() == path.get_start());
- assert(end .get_position() == path.get_end ());
- assert(start.get_owner () == end .get_owner());
-
- Player & owner = start.owner();
- Road & road = *new Road();
- road.set_owner(&owner);
- road.m_type = Road_Normal;
- road.m_flags[FlagStart] = &start;
- road.m_flags[FlagEnd] = &end;
- // m_flagidx is set when attach_road() is called, i.e. in init()
- road._set_path(egbase, path);
-
- road.init(egbase);
-
- return road;
-}
-
-int32_t Road::get_type() const throw ()
-{
- return ROAD;
-}
-
-int32_t Road::get_size() const throw ()
-{
- return SMALL;
-}
-
-bool Road::get_passable() const throw ()
-{
- return true;
-}
-
-BaseImmovable::PositionList Road::get_positions
- (const Editor_Game_Base & egbase) const throw ()
-{
- Map & map = egbase.map();
- Coords curf = map.get_fcoords(m_path.get_start());
-
- PositionList rv;
- const Path::Step_Vector::size_type nr_steps = m_path.get_nsteps();
- for (Path::Step_Vector::size_type steps = 0; steps < nr_steps + 1; ++steps)
- {
- if (steps > 0 && steps < m_path.get_nsteps())
- rv.push_back(curf);
-
- if (steps < m_path.get_nsteps())
- map.get_neighbour(curf, m_path[steps], &curf);
- }
- return rv;
+Road& Road::create(Editor_Game_Base& egbase, Flag& start, Flag& end, const Path& path) {
+ assert(start.get_position() == path.get_start());
+ assert(end.get_position() == path.get_end());
+ assert(start.get_owner() == end.get_owner());
+
+ Player& owner = start.owner();
+ Road& road = *new Road();
+ road.set_owner(&owner);
+ road.m_type = Road_Normal;
+ road.m_flags[FlagStart] = &start;
+ road.m_flags[FlagEnd] = &end;
+ // m_flagidx is set when attach_road() is called, i.e. in init()
+ road._set_path(egbase, path);
+
+ road.init(egbase);
+
+ return road;
+}
+
+int32_t Road::get_type() const throw() { return ROAD; }
+
+int32_t Road::get_size() const throw() { return SMALL; }
+
+bool Road::get_passable() const throw() { return true; }
+
+BaseImmovable::PositionList Road::get_positions(const Editor_Game_Base& egbase) const throw() {
+ Map& map = egbase.map();
+ Coords curf = map.get_fcoords(m_path.get_start());
+
+ PositionList rv;
+ const Path::Step_Vector::size_type nr_steps = m_path.get_nsteps();
+ for (Path::Step_Vector::size_type steps = 0; steps < nr_steps + 1; ++steps) {
+ if (steps > 0 && steps < m_path.get_nsteps())
+ rv.push_back(curf);
+
+ if (steps < m_path.get_nsteps())
+ map.get_neighbour(curf, m_path[steps], &curf);
+ }
+ return rv;
}
static std::string const road_name = "road";
-const std::string & Road::name() const throw () {return road_name;}
-
-
-Flag & Road::base_flag()
-{
- return *m_flags[FlagStart];
-}
+const std::string& Road::name() const throw() { return road_name; }
+
+Flag& Road::base_flag() { return *m_flags[FlagStart]; }
/**
* Return the cost of getting from fromflag to the other flag.
*/
-int32_t Road::get_cost(FlagId fromflag)
-{
- return m_cost[fromflag];
-}
+int32_t Road::get_cost(FlagId fromflag) { return m_cost[fromflag]; }
/**
* Set the new path, calculate costs.
* You have to set start and end flags before calling this function.
*/
-void Road::_set_path(Editor_Game_Base & egbase, const Path & path)
-{
- assert(path.get_nsteps() >= 2);
- assert(path.get_start() == m_flags[FlagStart]->get_position());
- assert(path.get_end() == m_flags[FlagEnd]->get_position());
-
- m_path = path;
- egbase.map().calc_cost(path, &m_cost[FlagStart], &m_cost[FlagEnd]);
-
- // Figure out where carriers should idle
- m_idle_index = path.get_nsteps() / 2;
+void Road::_set_path(Editor_Game_Base& egbase, const Path& path) {
+ assert(path.get_nsteps() >= 2);
+ assert(path.get_start() == m_flags[FlagStart]->get_position());
+ assert(path.get_end() == m_flags[FlagEnd]->get_position());
+
+ m_path = path;
+ egbase.map().calc_cost(path, &m_cost[FlagStart], &m_cost[FlagEnd]);
+
+ // Figure out where carriers should idle
+ m_idle_index = path.get_nsteps() / 2;
}
/**
* Add road markings to the map
*/
-void Road::_mark_map(Editor_Game_Base & egbase)
-{
- Map & map = egbase.map();
- FCoords curf = map.get_fcoords(m_path.get_start());
-
- const Path::Step_Vector::size_type nr_steps = m_path.get_nsteps();
- for (Path::Step_Vector::size_type steps = 0; steps < nr_steps + 1; ++steps)
- {
- if (steps > 0 && steps < m_path.get_nsteps())
- set_position(egbase, curf);
-
- // mark the road that leads up to this field
- if (steps > 0) {
- const Direction dir = get_reverse_dir(m_path[steps - 1]);
- Direction const rdir = 2 * (dir - WALK_E);
-
- if (rdir <= 4)
- egbase.set_road(curf, rdir, m_type);
- }
-
- // mark the road that leads away from this field
- if (steps < m_path.get_nsteps()) {
- const Direction dir = m_path[steps];
- Direction const rdir = 2 * (dir - WALK_E);
-
- if (rdir <= 4)
- egbase.set_road(curf, rdir, m_type);
-
- map.get_neighbour(curf, dir, &curf);
- }
- }
+void Road::_mark_map(Editor_Game_Base& egbase) {
+ Map& map = egbase.map();
+ FCoords curf = map.get_fcoords(m_path.get_start());
+
+ const Path::Step_Vector::size_type nr_steps = m_path.get_nsteps();
+ for (Path::Step_Vector::size_type steps = 0; steps < nr_steps + 1; ++steps) {
+ if (steps > 0 && steps < m_path.get_nsteps())
+ set_position(egbase, curf);
+
+ // mark the road that leads up to this field
+ if (steps > 0) {
+ const Direction dir = get_reverse_dir(m_path[steps - 1]);
+ Direction const rdir = 2 * (dir - WALK_E);
+
+ if (rdir <= 4)
+ egbase.set_road(curf, rdir, m_type);
+ }
+
+ // mark the road that leads away from this field
+ if (steps < m_path.get_nsteps()) {
+ const Direction dir = m_path[steps];
+ Direction const rdir = 2 * (dir - WALK_E);
+
+ if (rdir <= 4)
+ egbase.set_road(curf, rdir, m_type);
+
+ map.get_neighbour(curf, dir, &curf);
+ }
+ }
}
/**
* Remove road markings from the map
*/
-void Road::_unmark_map(Editor_Game_Base & egbase) {
- Map & map = egbase.map();
- FCoords curf(m_path.get_start(), &map[m_path.get_start()]);
-
- const Path::Step_Vector::size_type nr_steps = m_path.get_nsteps();
- for (Path::Step_Vector::size_type steps = 0; steps < nr_steps + 1; ++steps)
- {
- if (steps > 0 && steps < m_path.get_nsteps())
- unset_position(egbase, curf);
-
- // mark the road that leads up to this field
- if (steps > 0) {
- const Direction dir = get_reverse_dir(m_path[steps - 1]);
- Direction const rdir = 2 * (dir - WALK_E);
-
- if (rdir <= 4)
- egbase.set_road(curf, rdir, Road_None);
- }
-
- // mark the road that leads away from this field
- if (steps < m_path.get_nsteps()) {
- const Direction dir = m_path[steps];
- Direction const rdir = 2 * (dir - WALK_E);
-
- if (rdir <= 4)
- egbase.set_road(curf, rdir, Road_None);
-
- map.get_neighbour(curf, dir, &curf);
- }
- }
+void Road::_unmark_map(Editor_Game_Base& egbase) {
+ Map& map = egbase.map();
+ FCoords curf(m_path.get_start(), &map[m_path.get_start()]);
+
+ const Path::Step_Vector::size_type nr_steps = m_path.get_nsteps();
+ for (Path::Step_Vector::size_type steps = 0; steps < nr_steps + 1; ++steps) {
+ if (steps > 0 && steps < m_path.get_nsteps())
+ unset_position(egbase, curf);
+
+ // mark the road that leads up to this field
+ if (steps > 0) {
+ const Direction dir = get_reverse_dir(m_path[steps - 1]);
+ Direction const rdir = 2 * (dir - WALK_E);
+
+ if (rdir <= 4)
+ egbase.set_road(curf, rdir, Road_None);
+ }
+
+ // mark the road that leads away from this field
+ if (steps < m_path.get_nsteps()) {
+ const Direction dir = m_path[steps];
+ Direction const rdir = 2 * (dir - WALK_E);
+
+ if (rdir <= 4)
+ egbase.set_road(curf, rdir, Road_None);
+
+ map.get_neighbour(curf, dir, &curf);
+ }
+ }
}
/**
* Initialize the road.
*/
-void Road::init(Editor_Game_Base & egbase)
-{
- PlayerImmovable::init(egbase);
+void Road::init(Editor_Game_Base& egbase) {
+ PlayerImmovable::init(egbase);
- if (2 <= m_path.get_nsteps())
- _link_into_flags(egbase);
+ if (2 <= m_path.get_nsteps())
+ _link_into_flags(egbase);
}
/**
@@ -265,88 +228,82 @@
* we needed to have this road already registered
* as Map Object, thats why this is moved
*/
-void Road::_link_into_flags(Editor_Game_Base & egbase) {
- assert(m_path.get_nsteps() >= 2);
-
- // Link into the flags (this will also set our economy)
- {
- const Direction dir = m_path[0];
- m_flags[FlagStart]->attach_road(dir, this);
- m_flagidx[FlagStart] = dir;
- }
-
-
- const Direction dir =
- get_reverse_dir(m_path[m_path.get_nsteps() - 1]);
- m_flags[FlagEnd]->attach_road(dir, this);
- m_flagidx[FlagEnd] = dir;
-
- Economy::check_merge(*m_flags[FlagStart], *m_flags[FlagEnd]);
-
- // Mark Fields
- _mark_map(egbase);
-
- /*
- * Iterate over all Carrierslots
- * If a carrier is set assign it to this road, else
- * request a new carrier
- */
- if (upcast(Game, game, &egbase))
- container_iterate(SlotVector, m_carrier_slots, i) {
- if (Carrier * const carrier = i.current->carrier.get(*game)) {
- // This happens after a road split. Tell the carrier what's going on.
- carrier->set_location (this);
- carrier->update_task_road(*game);
- } else if
- (not i.current->carrier_request and
- (i.current->carrier_type == 1 or
- m_type == Road_Busy))
- _request_carrier(*i.current);
- }
+void Road::_link_into_flags(Editor_Game_Base& egbase) {
+ assert(m_path.get_nsteps() >= 2);
+
+ // Link into the flags (this will also set our economy)
+ {
+ const Direction dir = m_path[0];
+ m_flags[FlagStart]->attach_road(dir, this);
+ m_flagidx[FlagStart] = dir;
+ }
+
+ const Direction dir = get_reverse_dir(m_path[m_path.get_nsteps() - 1]);
+ m_flags[FlagEnd]->attach_road(dir, this);
+ m_flagidx[FlagEnd] = dir;
+
+ Economy::check_merge(*m_flags[FlagStart], *m_flags[FlagEnd]);
+
+ // Mark Fields
+ _mark_map(egbase);
+
+ /*
+ * Iterate over all Carrierslots
+ * If a carrier is set assign it to this road, else
+ * request a new carrier
+ */
+ if (upcast(Game, game, &egbase))
+ container_iterate(SlotVector, m_carrier_slots, i) {
+ if (Carrier* const carrier = i.current->carrier.get(*game)) {
+ // This happens after a road split. Tell the carrier what's going on.
+ carrier->set_location(this);
+ carrier->update_task_road(*game);
+ } else if (not i.current->carrier_request and(i.current->carrier_type == 1 or m_type ==
+ Road_Busy))
+ _request_carrier(*i.current);
+ }
}
/**
* Cleanup the road
*/
-void Road::cleanup(Editor_Game_Base & egbase)
-{
-
- container_iterate(SlotVector, m_carrier_slots, i) {
- delete i.current->carrier_request;
- i.current->carrier_request = 0;
-
- // carrier will be released via PlayerImmovable::cleanup
- i.current->carrier = 0;
- }
-
- // Unmark Fields
- _unmark_map(egbase);
-
- // Unlink from flags (also clears the economy)
- m_flags[FlagStart]->detach_road(m_flagidx[FlagStart]);
- m_flags[FlagEnd]->detach_road(m_flagidx[FlagEnd]);
-
- Economy::check_split(*m_flags[FlagStart], *m_flags[FlagEnd]);
-
- if (upcast(Game, game, &egbase)) {
- m_flags[FlagStart]->update_items(*game, m_flags[FlagEnd]);
- m_flags[FlagEnd]->update_items(*game, m_flags[FlagStart]);
- }
-
- PlayerImmovable::cleanup(egbase);
+void Road::cleanup(Editor_Game_Base& egbase) {
+
+ container_iterate(SlotVector, m_carrier_slots, i) {
+ delete i.current->carrier_request;
+ i.current->carrier_request = 0;
+
+ // carrier will be released via PlayerImmovable::cleanup
+ i.current->carrier = 0;
+ }
+
+ // Unmark Fields
+ _unmark_map(egbase);
+
+ // Unlink from flags (also clears the economy)
+ m_flags[FlagStart]->detach_road(m_flagidx[FlagStart]);
+ m_flags[FlagEnd]->detach_road(m_flagidx[FlagEnd]);
+
+ Economy::check_split(*m_flags[FlagStart], *m_flags[FlagEnd]);
+
+ if (upcast(Game, game, &egbase)) {
+ m_flags[FlagStart]->update_items(*game, m_flags[FlagEnd]);
+ m_flags[FlagEnd]->update_items(*game, m_flags[FlagStart]);
+ }
+
+ PlayerImmovable::cleanup(egbase);
}
/**
* Workers' economies are fixed by PlayerImmovable, but we need to handle
* any requests ourselves.
*/
-void Road::set_economy(Economy * const e)
-{
- PlayerImmovable::set_economy(e);
+void Road::set_economy(Economy* const e) {
+ PlayerImmovable::set_economy(e);
- container_iterate_const(SlotVector, m_carrier_slots, i)
- if (i.current->carrier_request)
- i.current->carrier_request->set_economy(e);
+ container_iterate_const(SlotVector, m_carrier_slots, i)
+ if (i.current->carrier_request)
+ i.current->carrier_request->set_economy(e);
}
/**
@@ -355,107 +312,93 @@
* Only call this if the road can handle a new carrier, and if no request has
* been issued.
*/
-void Road::_request_carrier(CarrierSlot & slot)
-{
- if (slot.carrier_type == 1)
- slot.carrier_request =
- new Request
- (*this,
- owner().tribe().safe_worker_index("carrier"),
- Road::_request_carrier_callback,
- wwWORKER);
- else
- slot.carrier_request =
- new Request
- (*this,
- owner().tribe().carrier2(),
- Road::_request_carrier_callback,
- wwWORKER);
+void Road::_request_carrier(CarrierSlot& slot) {
+ if (slot.carrier_type == 1)
+ slot.carrier_request = new Request(*this,
+ owner().tribe().safe_worker_index("carrier"),
+ Road::_request_carrier_callback,
+ wwWORKER);
+ else
+ slot.carrier_request =
+ new Request(*this, owner().tribe().carrier2(), Road::_request_carrier_callback, wwWORKER);
}
/**
* The carrier has arrived successfully.
*/
-void Road::_request_carrier_callback
- (Game & game,
- Request & rq,
- Ware_Index,
- Worker * const w,
- PlayerImmovable & target)
-{
- assert(w);
-
- Road & road = ref_cast<Road, PlayerImmovable>(target);
-
- container_iterate(SlotVector, road.m_carrier_slots, i)
- if (i.current->carrier_request == &rq) {
- Carrier & carrier = ref_cast<Carrier, Worker> (*w);
- i.current->carrier_request = 0;
- i.current->carrier = &carrier;
-
- carrier.start_task_road(game);
- delete &rq;
- return;
- }
-
- /*
- * Oops! We got a request_callback but don't have the request.
- * Try to send him home.
- */
- log
- ("Road(%u): got a request_callback but do not have the request\n",
- road.serial());
- delete &rq;
- w->start_task_gowarehouse(game);
+void Road::_request_carrier_callback(Game& game,
+ Request& rq,
+ Ware_Index,
+ Worker* const w,
+ PlayerImmovable& target) {
+ assert(w);
+
+ Road& road = ref_cast<Road, PlayerImmovable>(target);
+
+ container_iterate(SlotVector, road.m_carrier_slots, i)
+ if (i.current->carrier_request == &rq) {
+ Carrier& carrier = ref_cast<Carrier, Worker>(*w);
+ i.current->carrier_request = 0;
+ i.current->carrier = &carrier;
+
+ carrier.start_task_road(game);
+ delete &rq;
+ return;
+ }
+
+ /*
+ * Oops! We got a request_callback but don't have the request.
+ * Try to send him home.
+ */
+ log("Road(%u): got a request_callback but do not have the request\n", road.serial());
+ delete &rq;
+ w->start_task_gowarehouse(game);
}
/**
* If we lost our carrier, re-request it.
*/
-void Road::remove_worker(Worker & w)
-{
- Editor_Game_Base & egbase = owner().egbase();
-
- container_iterate(SlotVector, m_carrier_slots, i) {
- Carrier const * carrier = i.current->carrier.get(egbase);
-
- if (carrier == &w) {
- i.current->carrier = 0;
- carrier = 0;
- _request_carrier(*i.current);
- }
- }
-
- PlayerImmovable::remove_worker(w);
+void Road::remove_worker(Worker& w) {
+ Editor_Game_Base& egbase = owner().egbase();
+
+ container_iterate(SlotVector, m_carrier_slots, i) {
+ Carrier const* carrier = i.current->carrier.get(egbase);
+
+ if (carrier == &w) {
+ i.current->carrier = 0;
+ carrier = 0;
+ _request_carrier(*i.current);
+ }
+ }
+
+ PlayerImmovable::remove_worker(w);
}
/**
* A carrier was created by someone else (e.g. Scripting Engine)
* and should now be assigned to this road.
*/
-void Road::assign_carrier(Carrier & c, uint8_t slot)
-{
- assert(slot <= 1);
-
- // Send the worker home if it occupies our slot
- CarrierSlot & s = m_carrier_slots[slot];
-
- delete s.carrier_request;
- s.carrier_request = 0;
- if (Carrier * const current_carrier = s.carrier.get(owner().egbase()))
- current_carrier->set_location(0);
-
- m_carrier_slots[slot].carrier = &c;
- m_carrier_slots[slot].carrier_request = 0;
+void Road::assign_carrier(Carrier& c, uint8_t slot) {
+ assert(slot <= 1);
+
+ // Send the worker home if it occupies our slot
+ CarrierSlot& s = m_carrier_slots[slot];
+
+ delete s.carrier_request;
+ s.carrier_request = 0;
+ if (Carrier* const current_carrier = s.carrier.
Follow ups