smarter processing of MAKE TEMP.

the order gets its own keyword. parsing is hard - composite commands are an anti-pattern.
this eliminates a lot of unnecessary mallocs for pushing/poping parser state.
This commit is contained in:
Enno Rehling 2014-08-16 11:41:19 +02:00
parent 41d42fa248
commit c79dd33bfb
7 changed files with 733 additions and 751 deletions

View File

@ -2197,6 +2197,9 @@
<string name="make"> <string name="make">
<text locale="de">MACHEN</text> <text locale="de">MACHEN</text>
</string> </string>
<string name="maketemp">
<text locale="de">MACHE TEMP</text>
</string>
<string name="move"> <string name="move">
<text locale="de">NACH</text> <text locale="de">NACH</text>
</string> </string>

View File

@ -1475,6 +1475,9 @@
<string name="make"> <string name="make">
<text locale="en">MAKE</text> <text locale="en">MAKE</text>
</string> </string>
<string name="maketemp">
<text locale="de">MAKE TEMP</text>
</string>
<string name="move"> <string name="move">
<text locale="en">MOVE</text> <text locale="en">MOVE</text>
</string> </string>

View File

@ -1817,10 +1817,6 @@ int make_cmd(unit * u, struct order *ord)
p = findparam(s, u->faction->locale); p = findparam(s, u->faction->locale);
/* MACHE TEMP kann hier schon gar nicht auftauchen, weil diese nicht in
* thisorder abgespeichert werden - und auf den ist getstrtoken() beim
* aufruf von make geeicht */
if (p == P_ROAD) { if (p == P_ROAD) {
plane *pl = rplane(r); plane *pl = rplane(r);
if (pl && fval(pl, PFL_NOBUILD)) { if (pl && fval(pl, PFL_NOBUILD)) {
@ -1905,12 +1901,15 @@ int make_cmd(unit * u, struct order *ord)
else if (btype != NOBUILDING) { else if (btype != NOBUILDING) {
plane *pl = rplane(r); plane *pl = rplane(r);
if (pl && fval(pl, PFL_NOBUILD)) { if (pl && fval(pl, PFL_NOBUILD)) {
cmistake(u, ord, 94, MSG_PRODUCE); cmistake(u, ord, 275, MSG_PRODUCE);
} }
else { else if (btype->construction) {
int id = getid(); int id = getid();
build_building(u, btype, id, m, ord); build_building(u, btype, id, m, ord);
} }
else {
cmistake(u, ord, 275, MSG_PRODUCE);
}
} }
else if (itype != NULL) { else if (itype != NULL) {
create_item(u, itype, m); create_item(u, itype, m);

View File

@ -1571,16 +1571,17 @@ message *msg_unitnotfound(const struct unit * mage, struct order * ord,
{ {
/* Einheit nicht gefunden */ /* Einheit nicht gefunden */
char tbuf[20]; char tbuf[20];
const char *uid; const char *uid = 0;
if (spobj->typ == SPP_UNIT) { if (spobj->typ == SPP_TEMP) {
uid = itoa36(spobj->data.i);
}
else {
sprintf(tbuf, "%s %s", LOC(mage->faction->locale, sprintf(tbuf, "%s %s", LOC(mage->faction->locale,
parameters[P_TEMP]), itoa36(spobj->data.i)); parameters[P_TEMP]), itoa36(spobj->data.i));
uid = tbuf; uid = tbuf;
} }
else if (spobj->typ == SPP_UNIT) {
uid = itoa36(spobj->data.i);
}
assert(uid);
return msg_message("unitnotfound_id", return msg_message("unitnotfound_id",
"unit region command id", mage, mage->region, ord, uid); "unit region command id", mage, mage->region, ord, uid);
} }

View File

@ -359,6 +359,12 @@ order *parse_order(const char *s, const struct locale * lang)
} }
sptr = s; sptr = s;
kwd = get_keyword(parse_token(&sptr), lang); kwd = get_keyword(parse_token(&sptr), lang);
if (kwd == K_MAKE) {
const char *s = parse_token(&sptr);
if (isparam(s, lang, P_TEMP)) {
kwd = K_MAKETEMP;
}
}
if (kwd != NOKEYWORD) { if (kwd != NOKEYWORD) {
while (isxspace(*(unsigned char *)sptr)) ++sptr; while (isxspace(*(unsigned char *)sptr)) ++sptr;
s = sptr; s = sptr;
@ -380,7 +386,6 @@ bool is_repeated(const order * ord)
{ {
keyword_t kwd = ORD_KEYWORD(ord); keyword_t kwd = ORD_KEYWORD(ord);
const struct locale *lang = ORD_LOCALE(ord); const struct locale *lang = ORD_LOCALE(ord);
const char * s;
int result = 0; int result = 0;
switch (kwd) { switch (kwd) {
@ -402,23 +407,10 @@ bool is_repeated(const order * ord)
case K_BREED: case K_BREED:
case K_PIRACY: case K_PIRACY:
case K_PLANT: case K_PLANT:
case K_MAKE:
result = 1; result = 1;
break; break;
case K_MAKE:
/* Falls wir MACHE TEMP haben, ignorieren wir es. Alle anderen
* Arten von MACHE zaehlen aber als neue defaults und werden
* behandelt wie die anderen (deswegen kein break nach case
* K_MAKE) - und in thisorder (der aktuelle 30-Tage Befehl)
* abgespeichert). */
parser_pushstate();
init_tokens(ord); /* initialize token-parser */
skip_token();
s = getstrtoken();
result = !isparam(s, lang, P_TEMP);
parser_popstate();
// TODO: push/popstate is slow, we can do better.
break;
default: default:
result = 0; result = 0;
} }
@ -456,21 +448,10 @@ bool is_exclusive(const order * ord)
case K_BREED: case K_BREED:
case K_PIRACY: case K_PIRACY:
case K_PLANT: case K_PLANT:
case K_MAKE:
result = 1; result = 1;
break; break;
case K_MAKE:
/* Falls wir MACHE TEMP haben, ignorieren wir es. Alle anderen
* Arten von MACHE zaehlen aber als neue defaults und werden
* behandelt wie die anderen (deswegen kein break nach case
* K_MAKE) - und in thisorder (der aktuelle 30-Tage Befehl)
* abgespeichert). */
parser_pushstate();
init_tokens(ord); /* initialize token-parser */
skip_token();
result = !isparam(getstrtoken(), lang, P_TEMP);
parser_popstate();
break;
default: default:
result = 0; result = 0;
} }
@ -511,20 +492,9 @@ bool is_long(const order * ord)
case K_BREED: case K_BREED:
case K_PIRACY: case K_PIRACY:
case K_PLANT: case K_PLANT:
case K_MAKE:
return true; return true;
case K_MAKE:
/* Falls wir MACHE TEMP haben, ignorieren wir es. Alle anderen
* Arten von MACHE zaehlen aber als neue defaults und werden
* behandelt wie die anderen (deswegen kein break nach case
* K_MAKE) - und in thisorder (der aktuelle 30-Tage Befehl)
* abgespeichert). */
parser_pushstate();
init_tokens(ord); /* initialize token-parser */
skip_token();
result = !isparam(getstrtoken(), lang, P_TEMP);
parser_popstate();
break;
default: default:
result = false; result = false;
} }

View File

@ -3594,10 +3594,7 @@ void new_units(void)
while (*ordp) { while (*ordp) {
order *makeord = *ordp; order *makeord = *ordp;
if (getkeyword(makeord) == K_MAKE) { if (getkeyword(makeord) == K_MAKETEMP) {
init_tokens(makeord);
skip_token();
if (isparam(getstrtoken(), u->faction->locale, P_TEMP)) {
const char *token; const char *token;
char *name = NULL; char *name = NULL;
int alias; int alias;
@ -3660,7 +3657,6 @@ void new_units(void)
newordersp = &ord->next; newordersp = &ord->next;
} }
} }
}
if (*ordp == makeord) if (*ordp == makeord)
ordp = &makeord->next; ordp = &makeord->next;
} }

View File

@ -71,7 +71,8 @@ magic_t getmagicskill(const struct locale * lang)
if (tokens && s && s[0]) { if (tokens && s && s[0]) {
if (findtoken(*tokens, s, &token) == E_TOK_SUCCESS) { if (findtoken(*tokens, s, &token) == E_TOK_SUCCESS) {
return (magic_t)token.i; return (magic_t)token.i;
} else { }
else {
char buffer[3]; char buffer[3];
buffer[0] = s[0]; buffer[0] = s[0];
buffer[1] = s[1]; buffer[1] = s[1];
@ -208,7 +209,8 @@ teach_unit(unit * teacher, unit * student, int nteaching, skill_t sk,
if (teach == NULL) { if (teach == NULL) {
a = a_add(&student->attribs, a_new(&at_learning)); a = a_add(&student->attribs, a_new(&at_learning));
teach = (teaching_info *)a->data.v; teach = (teaching_info *)a->data.v;
} else { }
else {
while (teach->teachers[index] && index != MAXTEACHERS) while (teach->teachers[index] && index != MAXTEACHERS)
++index; ++index;
} }
@ -380,7 +382,8 @@ int teach_cmd(unit * u, struct order *ord)
student = student->next; student = student->next;
} }
#endif #endif
} else }
else
#endif #endif
{ {
char zOrder[4096]; char zOrder[4096];
@ -419,7 +422,8 @@ int teach_cmd(unit * u, struct order *ord)
sprintf(tbuf, "%s %s", LOC(u->faction->locale, sprintf(tbuf, "%s %s", LOC(u->faction->locale,
parameters[P_TEMP]), token); parameters[P_TEMP]), token);
uid = tbuf; uid = tbuf;
} else { }
else {
uid = token; uid = token;
} }
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "unitnotfound_id", ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "unitnotfound_id",
@ -616,7 +620,8 @@ int learn_cmd(unit * u, order * ord)
mtyp = M_GRAY; mtyp = M_GRAY;
if (!is_mage(u)) if (!is_mage(u))
create_mage(u, mtyp); create_mage(u, mtyp);
} else if (!has_skill(u, SK_MAGIC)) { }
else if (!has_skill(u, SK_MAGIC)) {
int mmax = skill_limit(u->faction, SK_MAGIC); int mmax = skill_limit(u->faction, SK_MAGIC);
/* Die Einheit ist noch kein Magier */ /* Die Einheit ist noch kein Magier */
if (count_skill(u->faction, SK_MAGIC) + u->number > mmax) { if (count_skill(u->faction, SK_MAGIC) + u->number > mmax) {
@ -630,7 +635,8 @@ int learn_cmd(unit * u, order * ord)
* ausgegangen, dass das normal gelernt werden soll */ * ausgegangen, dass das normal gelernt werden soll */
if (u->faction->magiegebiet != 0) { if (u->faction->magiegebiet != 0) {
mtyp = u->faction->magiegebiet; mtyp = u->faction->magiegebiet;
} else { }
else {
/* Es wurde kein Magiegebiet angegeben und die Partei /* Es wurde kein Magiegebiet angegeben und die Partei
* hat noch keins gewaehlt. */ * hat noch keins gewaehlt. */
mtyp = getmagicskill(u->faction->locale); mtyp = getmagicskill(u->faction->locale);
@ -646,7 +652,8 @@ int learn_cmd(unit * u, order * ord)
if (u->faction->magiegebiet != 0) { if (u->faction->magiegebiet != 0) {
cmistake(u, ord, 179, MSG_MAGIC); cmistake(u, ord, 179, MSG_MAGIC);
return 0; return 0;
} else { }
else {
/* Lernt zum ersten mal Magie und legt damit das /* Lernt zum ersten mal Magie und legt damit das
* Magiegebiet der Partei fest */ * Magiegebiet der Partei fest */
u->faction->magiegebiet = mtyp; u->faction->magiegebiet = mtyp;
@ -654,7 +661,8 @@ int learn_cmd(unit * u, order * ord)
} }
if (!is_mage(u)) if (!is_mage(u))
create_mage(u, mtyp); create_mage(u, mtyp);
} else { }
else {
/* ist schon ein Magier und kein Vertrauter */ /* ist schon ein Magier und kein Vertrauter */
if (u->faction->magiegebiet == 0) { if (u->faction->magiegebiet == 0) {
/* die Partei hat noch kein Magiegebiet gewaehlt. */ /* die Partei hat noch kein Magiegebiet gewaehlt. */
@ -750,7 +758,8 @@ int learn_cmd(unit * u, order * ord)
if (days >= u->number * 30) { if (days >= u->number * 30) {
learn_skill(u, sk, 1.0); learn_skill(u, sk, 1.0);
days -= u->number * 30; days -= u->number * 30;
} else { }
else {
double chance = (double)days / u->number / 30; double chance = (double)days / u->number / 30;
learn_skill(u, sk, chance); learn_skill(u, sk, chance);
days = 0; days = 0;
@ -798,7 +807,8 @@ int learn_cmd(unit * u, order * ord)
} }
} }
} }
} else if (sk == SK_MAGIC) { }
else if (sk == SK_MAGIC) {
sc_mage *mage = get_mage(u); sc_mage *mage = get_mage(u);
if (!mage) { if (!mage) {
mage = create_mage(u, u->faction->magiegebiet); mage = create_mage(u, u->faction->magiegebiet);