static void test_getstrtoken(CuTest *tc) {
    init_tokens_str("HELP ONE TWO THREE");
    CuAssertStrEquals(tc, "HELP", getstrtoken());
    CuAssertStrEquals(tc, "ONE", getstrtoken());
    CuAssertStrEquals(tc, "TWO", getstrtoken());
    CuAssertStrEquals(tc, "THREE", getstrtoken());
    CuAssertPtrEquals(tc, NULL, (void *)getstrtoken());
}
Beispiel #2
0
static void test_init_order(CuTest *tc) {
    order *ord;
    struct locale * lang = get_or_create_locale("en");

    ord = create_order(K_MAKETEMP, lang, "hurr durr");
    CuAssertIntEquals(tc, K_MAKETEMP, init_order(ord));
    CuAssertStrEquals(tc, "hurr", getstrtoken());
    CuAssertStrEquals(tc, "durr", getstrtoken());
}
Beispiel #3
0
int *parse_ids(const order *ord) {
    const char *s;
    int *il = NULL;

    init_order(ord);
    s = getstrtoken();
    if (s != NULL && *s) {
        il = intlist_init();
        while (s && *s) {
            il = intlist_add(il, atoi36(s));
            s = getstrtoken();
        }
    }
    return il;
}
Beispiel #4
0
static void gm_create(const void *tnext, struct unit *u, struct order *ord)
{
  int i;
  attrib *permissions = a_find(u->faction->attribs, &at_permissions);
  if (permissions)
    permissions = (attrib *) permissions->data.v;
  if (!permissions)
    return;
  i = getint();

  if (i > 0) {
    const char *iname = getstrtoken();
    const item_type *itype = finditemtype(iname, u->faction->locale);
    if (itype == NULL) {
      mistake(u, ord, "unknown item.");
    } else {
      attrib *a = a_find(permissions, &at_gmcreate);

      while (a && a->type == &at_gmcreate && a->data.v != (void *)itype)
        a = a->next;
      if (a)
        i_change(&u->items, itype, i);
      else
        mistake(u, ord, "your faction cannot create this item.");
    }
  }
}
Beispiel #5
0
/**
 ** GM: SKILL <unit> <skill> <tage>
 ** requires: permission-key "gmskil"
 **/
static void gm_skill(const void *tnext, struct unit *u, struct order *ord)
{
  unit *to = findunit(getid());
  skill_t skill = findskill(getstrtoken(), u->faction->locale);
  int num = getint();

  if (to == NULL || rplane(to->region) != rplane(u->region)) {
    /* unknown or in another plane */
    ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found",
        ""));
  } else if (skill == NOSKILL || skill == SK_MAGIC || skill == SK_ALCHEMY) {
    /* unknown or not enough */
    mistake(u, ord, "unknown skill, or skill cannot be raised.");
  } else if (num < 0 || num > 30) {
    /* sanity check failed */
    mistake(u, ord, "invalid value.");
  } else {
    /* checking permissions */
    attrib *permissions = a_find(u->faction->attribs, &at_permissions);
    if (!permissions || !has_permission(permissions, atoi36("gmskil"))) {
      mistake(u, ord, "permission denied.");
    } else {
      set_level(to, skill, num);
    }
  }
}
Beispiel #6
0
/** callback for an item-use function written in lua. */
int
lua_useitem(struct unit *u, const struct item_type *itype, int amount,
struct order *ord)
{
    lua_State *L = (lua_State *)global.vm_state;
    int result = 0;
    char fname[64];

    strlcpy(fname, "use_", sizeof(fname));
    strlcat(fname, itype->rtype->_name, sizeof(fname));

    lua_getglobal(L, fname);
    if (lua_isfunction(L, -1)) {
        tolua_pushusertype(L, (void *)u, TOLUA_CAST "unit");
        lua_pushinteger(L, amount);
        lua_pushstring(L, getstrtoken());
        tolua_pushusertype(L, (void *)ord, TOLUA_CAST "order");
        if (lua_pcall(L, 4, 1, 0) != 0) {
            const char *error = lua_tostring(L, -1);
            log_error("use(%s) calling '%s': %s.\n", unitname(u), fname, error);
            lua_pop(L, 1);
        }
        else {
            result = (int)lua_tonumber(L, -1);
            lua_pop(L, 1);
        }
    }
    else {
        log_error("use(%s) calling '%s': not a function.\n", unitname(u), fname);
        lua_pop(L, 1);
    }

    return result;
}
Beispiel #7
0
/**
 ** GM: TELL <unit> <string>
 ** requires: permission-key "gmmsgr"
 **/
static void gm_messageunit(const void *tnext, struct unit *u, struct order *ord)
{
  const struct plane *p = rplane(u->region);
  unit *target = findunit(getid());
  const char *msg = getstrtoken();
  region *r;

  if (target == NULL) {
    ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found",
        ""));
    return;
  }

  r = target->region;

  if (r == NULL || p != rplane(r)) {
    mistake(u, ord, "region is in another plane.");
  } else {
    /* checking permissions */
    attrib *permissions = a_find(u->faction->attribs, &at_permissions);
    if (!permissions || !has_permission(permissions, atoi36("gmmsgu"))) {
      mistake(u, ord, "permission denied.");
    } else {
      add_message(&target->faction->msgs,
        msg_message("regionmessage", "region sender string", r, u, msg));
    }
  }
}
Beispiel #8
0
/**
 ** GM: KILL FACTION <id> <string>
 ** requires: permission-key "gmmsgr"
 **/
static void gm_killfaction(const void *tnext, struct unit *u, struct order *ord)
{
  int n = getid();
  faction *f = findfaction(n);
  const char *msg = getstrtoken();
  plane *p = rplane(u->region);
  attrib *permissions = a_find(u->faction->attribs, &at_permissions);
  if (!permissions || !has_permission(permissions, atoi36("gmkill"))) {
    mistake(u, ord, "permission denied.");
    return;
  }
  if (f != NULL) {
    region *r;
    for (r = regions; r; r = r->next)
      if (rplane(r) == p) {
        unit *target;
        for (target = r->units; target; target = target->next) {
          if (target->faction == f) {
            scale_number(target, 0);
            ADDMSG(&target->faction->msgs, msg_message("killedbygm",
                "region unit string", r, target, msg));
            return;
          }
        }
      }
  }
  mistake(u, ord, "cannot remove a unit from this faction.");
}
Beispiel #9
0
static void
gm_messagefaction(const void *tnext, struct unit *gm, struct order *ord)
{
  int n = getid();
  faction *f = findfaction(n);
  const char *msg = getstrtoken();
  plane *p = rplane(gm->region);
  attrib *permissions = a_find(gm->faction->attribs, &at_permissions);
  if (!permissions || !has_permission(permissions, atoi36("gmmsgr"))) {
    mistake(gm, ord, "permission denied.");
    return;
  }
  if (f != NULL) {
    region *r;
    for (r = regions; r; r = r->next)
      if (rplane(r) == p) {
        unit *u;
        for (u = r->units; u; u = u->next)
          if (u->faction == f) {
            add_message(&f->msgs, msg_message("msg_event", "string", msg));
            return;
          }
      }
  }
  mistake(gm, ord, "cannot send messages to this faction.");
}
Beispiel #10
0
/**
 ** GM: TELL PLANE <string>
 ** requires: permission-key "gmmsgr"
 **/
static void gm_messageplane(const void *tnext, struct unit *gm, struct order *ord)
{
  const struct plane *p = rplane(gm->region);
  const char *zmsg = getstrtoken();
  if (p == NULL) {
    mistake(gm, ord, "In diese Ebene kann keine Nachricht gesandt werden.");
  } else {
    /* checking permissions */
    attrib *permissions = a_find(gm->faction->attribs, &at_permissions);
    if (!permissions || !has_permission(permissions, atoi36("gmmsgr"))) {
      mistake(gm, ord, "permission denied.");
    } else {
      message *msg = msg_message("msg_event", "string", zmsg);
      faction *f;
      region *r;
      for (f = factions; f; f = f->next) {
        freset(f, FFL_SELECT);
      }
      for (r = regions; r; r = r->next) {
        unit *u;
        if (rplane(r) != p)
          continue;
        for (u = r->units; u; u = u->next)
          if (!fval(u->faction, FFL_SELECT)) {
            f = u->faction;
            fset(f, FFL_SELECT);
            add_message(&f->msgs, msg);
          }
      }
      msg_release(msg);
    }
  }
}
Beispiel #11
0
/**
 ** GM: TERRAFORM <x> <y> <terrain>
 ** requires: permission-key "gmterf"
 **/
static void gm_terraform(const void *tnext, struct unit *u, struct order *ord)
{
  const struct plane *p = rplane(u->region);
  int x = rel_to_abs(p, u->faction, getint(), 0);
  int y = rel_to_abs(p, u->faction, getint(), 1);
  const char *c = getstrtoken();
  variant token;
  void **tokens = get_translations(u->faction->locale, UT_TERRAINS);
  region *r;
  pnormalize(&x, &y, p);
  r = findregion(x, y);

  if (r == NULL || p != rplane(r)) {
    mistake(u, ord, "region is in another plane.");
    return;
  } else {
    /* checking permissions */
    attrib *permissions = a_find(u->faction->attribs, &at_permissions);
    if (!permissions || !has_permission(permissions, atoi36("gmterf")))
      return;
  }

  if (findtoken(*tokens, c, &token) != E_TOK_NOMATCH) {
    const terrain_type *terrain = (const terrain_type *)token.v;
    terraform_region(r, terrain);
  }
}
Beispiel #12
0
/**
 ** GM: TAKE <unit> <int> <itemtype>
 ** requires: permission-key "gmtake"
 **/
static void gm_take(const void *tnext, struct unit *u, struct order *ord)
{
  unit *to = findunit(getid());
  int num = getint();
  const item_type *itype = finditemtype(getstrtoken(), u->faction->locale);

  if (to == NULL || rplane(to->region) != rplane(u->region)) {
    /* unknown or in another plane */
    ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found",
        ""));
  } else if (itype == NULL || i_get(to->items, itype) == 0) {
    /* unknown or not enough */
    mistake(u, ord, "invalid item or item not found.");
  } else {
    /* checking permissions */
    attrib *permissions = a_find(u->faction->attribs, &at_permissions);
    if (!permissions || !has_permission(permissions, atoi36("gmtake"))) {
      mistake(u, ord, "permission denied.");
    } else {
      int i = i_get(to->items, itype);
      if (i < num)
        num = i;
      if (num) {
        i_change(&to->items, itype, -num);
        i_change(&u->items, itype, num);
      }
    }
  }
}
Beispiel #13
0
static int tolua_order_get_token(lua_State *L) {
    order *ord = (order *)tolua_tousertype(L, 1, 0);
    int n = (int)tolua_tonumber(L, 2, 0);
    const char * str = 0;
    init_order(ord);
    while (n-->0) {
        str = getstrtoken();
        if (!str) {
            return 0;
        }
    }

    tolua_pushstring(L, str);
    return 1;
}
Beispiel #14
0
static void test_getstrtoken(CuTest *tc) {
    init_tokens_str("hurr \"durr\" \"\" \'\'");
    CuAssertStrEquals(tc, "hurr", getstrtoken());
    CuAssertStrEquals(tc, "durr", getstrtoken());
    CuAssertStrEquals(tc, "", getstrtoken());
    CuAssertStrEquals(tc, "", getstrtoken());
    CuAssertStrEquals(tc, 0, getstrtoken());
    init_tokens_str(0);
    CuAssertStrEquals(tc, 0, getstrtoken());
}
Beispiel #15
0
static void test_parse_maketemp(CuTest *tc) {
    char cmd[32];
    order *ord;
    struct locale * lang = get_or_create_locale("en");

    locale_setstring(lang, keyword(K_MAKE), "MAKE");
    locale_setstring(lang, keyword(K_MAKETEMP), "MAKETEMP");
    locale_setstring(lang, "TEMP", "TEMP");
    init_locale(lang);

    ord = parse_order("MAKET herp", lang);
    CuAssertPtrNotNull(tc, ord);
    CuAssertStrEquals(tc, "MAKETEMP herp", get_command(ord, cmd, sizeof(cmd)));
    CuAssertIntEquals(tc, K_MAKETEMP, getkeyword(ord));
    CuAssertIntEquals(tc, K_MAKETEMP, init_order(ord));
    CuAssertStrEquals(tc, "herp", getstrtoken());
    free_order(ord);
}
Beispiel #16
0
static void test_create_order(CuTest *tc) {
    char cmd[32];
    order *ord;
    struct locale * lang;

    test_cleanup();
    lang = get_or_create_locale("en");

    locale_setstring(lang, "keyword::move", "MOVE");
    ord = create_order(K_MOVE, lang, "NORTH");
    CuAssertPtrNotNull(tc, ord);
    CuAssertIntEquals(tc, K_MOVE, getkeyword(ord));
    CuAssertStrEquals(tc, "MOVE NORTH", get_command(ord, cmd, sizeof(cmd)));

    CuAssertIntEquals(tc, K_MOVE, init_order(ord));
    CuAssertStrEquals(tc, "NORTH", getstrtoken());
    free_order(ord);
    test_cleanup();
}
Beispiel #17
0
/**
 ** GM: TELL REGION <x> <y> <string>
 ** requires: permission-key "gmmsgr"
 **/
static void gm_messageregion(const void *tnext, struct unit *u, struct order *ord)
{
  const struct plane *p = rplane(u->region);
  int x = rel_to_abs(p, u->faction, getint(), 0);
  int y = rel_to_abs(p, u->faction, getint(), 1);
  const char *msg = getstrtoken();
  region *r = findregion(x, y);

  if (r == NULL || p != rplane(r)) {
    mistake(u, ord, "region is in another plane.");
  } else {
    /* checking permissions */
    attrib *permissions = a_find(u->faction->attribs, &at_permissions);
    if (!permissions || !has_permission(permissions, atoi36("gmmsgr"))) {
      mistake(u, ord, "permission denied.");
    } else {
      add_message(&r->msgs, msg_message("msg_event", "string", msg));
    }
  }
}
Beispiel #18
0
/**
 ** GM: KILL UNIT <id> <string>
 ** requires: permission-key "gmkill"
 **/
static void gm_killunit(const void *tnext, struct unit *u, struct order *ord)
{
  const struct plane *p = rplane(u->region);
  unit *target = findunit(getid());
  const char *msg = getstrtoken();
  region *r = target->region;

  if (r == NULL || p != rplane(r)) {
    mistake(u, ord, "region is in another plane.");
  } else {
    /* checking permissions */
    attrib *permissions = a_find(u->faction->attribs, &at_permissions);
    if (!permissions || !has_permission(permissions, atoi36("gmkill"))) {
      mistake(u, ord, "permission denied.");
    } else {
      scale_number(target, 0);
      ADDMSG(&target->faction->msgs, msg_message("killedbygm",
          "region unit string", r, target, msg));
    }
  }
}
Beispiel #19
0
magic_t getmagicskill(const struct locale * lang)
{
    void **tokens = get_translations(lang, UT_MAGIC);
    variant token;
    const char *s = getstrtoken();

    if (tokens && s && s[0]) {
        if (findtoken(*tokens, s, &token) == E_TOK_SUCCESS) {
            return (magic_t)token.i;
        }
        else {
            char buffer[8];
            buffer[0] = s[0];
            buffer[1] = s[1];
            buffer[2] = '\0';
            if (findtoken(*tokens, buffer, &token) == E_TOK_SUCCESS) {
                return (magic_t)token.i;
            }
        }
    }
    return M_NONE;
}
Beispiel #20
0
/** callback for an item-use function written in lua. */
static int
lua_use_item(unit *u, const item_type *itype, const char * fname, int amount, struct order *ord)
{
    lua_State *L = (lua_State *)global.vm_state;

    lua_getglobal(L, fname);
    if (lua_isfunction(L, -1)) {
        tolua_pushusertype(L, (void *)u, TOLUA_CAST "unit");
        lua_pushinteger(L, amount);
        lua_pushstring(L, getstrtoken());
        tolua_pushusertype(L, (void *)ord, TOLUA_CAST "order");
        if (lua_pcall(L, 4, 1, 0) != 0) {
            const char *error = lua_tostring(L, -1);
            log_error("use(%s) calling '%s': %s.\n", unitname(u), fname, error);
        }
        else {
            int result = (int)lua_tonumber(L, -1);
            lua_pop(L, 1);
            return result;
        }
    }
    lua_pop(L, 1);
    return 0;
}
Beispiel #21
0
static void test_skip_token(CuTest *tc) {
    init_tokens_str("hurr \"durr\"");
    skip_token();
    CuAssertStrEquals(tc, "durr", getstrtoken());
    CuAssertStrEquals(tc, 0, getstrtoken());
}
Beispiel #22
0
int teach_cmd(unit * u, struct order *ord)
{
    static const curse_type *gbdream_ct = NULL;
    plane *pl;
    region *r = u->region;
    int teaching, i, j, count, academy = 0;
    skill_t sk = NOSKILL;

    if (gbdream_ct == 0)
        gbdream_ct = ct_find("gbdream");
    if (gbdream_ct) {
        if (get_curse(u->region->attribs, gbdream_ct)) {
            ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "gbdream_noteach", ""));
            return 0;
        }
    }

    if ((u_race(u)->flags & RCF_NOTEACH) || fval(u, UFL_WERE)) {
        cmistake(u, ord, 274, MSG_EVENT);
        return 0;
    }

    pl = rplane(r);
    if (pl && fval(pl, PFL_NOTEACH)) {
        cmistake(u, ord, 273, MSG_EVENT);
        return 0;
    }

    teaching = u->number * 30 * TEACHNUMBER;

    if ((i = get_effect(u, oldpotiontype[P_FOOL])) > 0) { /* Trank "Dumpfbackenbrot" */
        i = _min(i, u->number * TEACHNUMBER);
        /* Trank wirkt pro Schueler, nicht pro Lehrer */
        teaching -= i * 30;
        change_effect(u, oldpotiontype[P_FOOL], -i);
        j = teaching / 30;
        ADDMSG(&u->faction->msgs, msg_message("teachdumb", "teacher amount", u, j));
    }
    if (teaching == 0)
        return 0;

    count = 0;

    init_order(ord);

#if TEACH_ALL
    if (getparam(u->faction->locale) == P_ANY) {
        unit *student = r->units;
        skill_t teachskill[MAXSKILLS];
        int i = 0;
        do {
            sk = getskill(u->faction->locale);
            teachskill[i++] = sk;
        } while (sk != NOSKILL);
        while (teaching && student) {
            if (student->faction == u->faction) {
                if (LongHunger(student))
                    continue;
                if (getkeyword(student->thisorder) == K_STUDY) {
                    /* Input ist nun von student->thisorder !! */
                    init_order(student->thisorder);
                    sk = getskill(student->faction->locale);
                    if (sk != NOSKILL && teachskill[0] != NOSKILL) {
                        for (i = 0; teachskill[i] != NOSKILL; ++i)
                            if (sk == teachskill[i])
                                break;
                        sk = teachskill[i];
                    }
                    if (sk != NOSKILL
                        && eff_skill_study(u, sk,
                        r) - TEACHDIFFERENCE > eff_skill_study(student, sk, r)) {
                        teaching -= teach_unit(u, student, teaching, sk, true, &academy);
                    }
                }
            }
            student = student->next;
        }
#ifdef TEACH_FRIENDS
        while (teaching && student) {
            if (student->faction != u->faction
                && alliedunit(u, student->faction, HELP_GUARD)) {
                if (LongHunger(student))
                    continue;
                if (getkeyword(student->thisorder) == K_STUDY) {
                    /* Input ist nun von student->thisorder !! */
                    init_order(student->thisorder);
                    sk = getskill(student->faction->locale);
                    if (sk != NOSKILL
                        && eff_skill_study(u, sk, r) - TEACHDIFFERENCE >= eff_skill(student,
                        sk, r)) {
                        teaching -= teach_unit(u, student, teaching, sk, true, &academy);
                    }
                }
            }
            student = student->next;
        }
#endif
    }
    else
#endif
    {
        char zOrder[4096];
        order *new_order;

        zOrder[0] = '\0';
        init_order(ord);

        while (!parser_end()) {
            unit *u2;
            bool feedback;

            getunit(r, u->faction, &u2);
            ++count;

            /* Falls die Unit nicht gefunden wird, Fehler melden */

            if (!u2) {
                char tbuf[20];
                const char *uid;
                const char *token;
                /* Finde den string, der den Fehler verursacht hat */
                parser_pushstate();
                init_order(ord);

                for (j = 0; j != count - 1; ++j) {
                    /* skip over the first 'count' units */
                    getunit(r, u->faction, NULL);
                }

                token = getstrtoken();

                /* Beginne die Fehlermeldung */
                if (isparam(token, u->faction->locale, P_TEMP)) {
                    token = getstrtoken();
                    sprintf(tbuf, "%s %s", LOC(u->faction->locale,
                        parameters[P_TEMP]), token);
                    uid = tbuf;
                }
                else {
                    uid = token;
                }
                ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "unitnotfound_id",
                    "id", uid));

                parser_popstate();
                continue;
            }

            feedback = u->faction == u2->faction
                || alliedunit(u2, u->faction, HELP_GUARD);

            /* Neuen Befehl zusammenbauen. TEMP-Einheiten werden automatisch in
             * ihre neuen Nummern uebersetzt. */
            if (zOrder[0])
                strcat(zOrder, " ");
            strcat(zOrder, unitid(u2));

            if (getkeyword(u2->thisorder) != K_STUDY) {
                ADDMSG(&u->faction->msgs,
                    msg_feedback(u, ord, "teach_nolearn", "student", u2));
                continue;
            }

            /* Input ist nun von u2->thisorder !! */
            parser_pushstate();
            init_order(u2->thisorder);
            sk = getskill(u2->faction->locale);
            parser_popstate();

            if (sk == NOSKILL) {
                ADDMSG(&u->faction->msgs,
                    msg_feedback(u, ord, "teach_nolearn", "student", u2));
                continue;
            }

            /* u is teacher, u2 is student */
            if (eff_skill_study(u2, sk, r) > eff_skill_study(u, sk,
                r) - TEACHDIFFERENCE) {
                if (feedback) {
                    ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "teach_asgood",
                        "student", u2));
                }
                continue;
            }
            if (sk == SK_MAGIC) {
                /* ist der Magier schon spezialisiert, so versteht er nur noch
                 * Lehrer seines Gebietes */
                sc_mage *mage1 = get_mage(u);
                sc_mage *mage2 = get_mage(u2);
                if (!mage2 || !mage1 || (mage2->magietyp != M_GRAY
                    && mage1->magietyp != mage2->magietyp)) {
                    if (feedback) {
                        ADDMSG(&u->faction->msgs, msg_feedback(u, ord,
                            "error_different_magic", "target", u2));
                    }
                    continue;
                }
            }

            teaching -= teach_unit(u, u2, teaching, sk, false, &academy);
        }
        new_order = create_order(K_TEACH, u->faction->locale, "%s", zOrder);
        replace_order(&u->orders, ord, new_order);
        free_order(new_order);      /* parse_order & set_order have each increased the refcount */
    }
    if (academy && sk != NOSKILL) {
        academy = academy / 30;     /* anzahl gelehrter wochen, max. 10 */
        learn_skill(u, sk, academy / 30.0 / TEACHNUMBER);
    }
    return 0;
}
Beispiel #23
0
int teach_cmd(unit * teacher, struct order *ord)
{
    plane *pl;
    region *r = teacher->region;
    skill_t sk_academy = NOSKILL;
    int teaching, i, j, count, academy_students = 0;

    if (r->attribs) {
        if (get_curse(r->attribs, &ct_gbdream)) {
            ADDMSG(&teacher->faction->msgs,
                msg_feedback(teacher, ord, "gbdream_noteach", ""));
            return 0;
        }
    }
    if ((u_race(teacher)->flags & RCF_NOTEACH) || fval(teacher, UFL_WERE)) {
        cmistake(teacher, ord, 274, MSG_EVENT);
        return 0;
    }

    pl = rplane(r);
    if (pl && fval(pl, PFL_NOTEACH)) {
        cmistake(teacher, ord, 273, MSG_EVENT);
        return 0;
    }

    teaching = teacher->number  * TEACHNUMBER;

    if ((i = get_effect(teacher, oldpotiontype[P_FOOL])) > 0) { /* Trank "Dumpfbackenbrot" */
        if (i > teaching) i = teaching;
        /* Trank wirkt pro Schueler, nicht pro Lehrer */
        teaching -= i;
        change_effect(teacher, oldpotiontype[P_FOOL], -i);
        j = teaching;
        ADDMSG(&teacher->faction->msgs, msg_message("teachdumb", "teacher amount", teacher, j));
    }
    if (teaching <= 0)
        return 0;

    count = 0;

    init_order_depr(ord);

#if TEACH_ALL
    if (getparam(teacher->faction->locale) == P_ANY) {
        skill_t sk;
        unit *scholar;
        skill_t teachskill[MAXSKILLS];
        int t = 0;

        do {
            sk = getskill(teacher->faction->locale);
            teachskill[t] = getskill(teacher->faction->locale);
        } while (sk != NOSKILL);

        for (scholar = r->units; teaching > 0 && scholar; scholar = scholar->next) {
            if (LongHunger(scholar)) {
                continue;
            }
            else if (scholar->faction == teacher->faction) {
                if (getkeyword(scholar->thisorder) == K_STUDY) {
                    /* Input ist nun von student->thisorder !! */
                    init_order(scholar->thisorder, scholar->faction->locale);
                    sk = getskill(scholar->faction->locale);
                    if (sk != NOSKILL && teachskill[0] != NOSKILL) {
                        for (t = 0; teachskill[t] != NOSKILL; ++t) {
                            if (sk == teachskill[t]) {
                                break;
                            }
                        }
                        sk = teachskill[t];
                    }
                    if (sk != NOSKILL
                        && effskill_study(teacher, sk) - TEACHDIFFERENCE > effskill_study(scholar, sk)) {
                        teaching -= teach_unit(teacher, scholar, teaching, sk, true, &academy_students);
                    }
                }
            }
#ifdef TEACH_FRIENDS
            else if (alliedunit(teacher, scholar->faction, HELP_GUARD)) {
                if (getkeyword(scholar->thisorder) == K_STUDY) {
                    /* Input ist nun von student->thisorder !! */
                    init_order(scholar->thisorder, scholar->faction->locale);
                    sk = getskill(scholar->faction->locale);
                    if (sk != NOSKILL
                        && effskill_study(teacher, sk) - TEACHDIFFERENCE >= effskill(scholar, sk, NULL)) {
                        teaching -= teach_unit(teacher, scholar, teaching, sk, true, &academy_students);
                    }
                }
            }
#endif
        }
    }
    else
#endif
    {
        char zOrder[4096];
        size_t sz = sizeof(zOrder);
        order *new_order;

        zOrder[0] = '\0';
        init_order_depr(ord);

        while (!parser_end()) {
            skill_t sk;
            unit *scholar;
            bool feedback;

            getunit(r, teacher->faction, &scholar);
            ++count;

            /* Falls die Unit nicht gefunden wird, Fehler melden */

            if (!scholar) {
                char tbuf[20];
                const char *uid;
                const char *token;
                /* Finde den string, der den Fehler verursacht hat */
                parser_pushstate();
                init_order_depr(ord);

                for (j = 0; j != count - 1; ++j) {
                    /* skip over the first 'count' units */
                    getunit(r, teacher->faction, NULL);
                }

                token = getstrtoken();

                /* Beginne die Fehlermeldung */
                if (isparam(token, teacher->faction->locale, P_TEMP)) {
                    token = getstrtoken();
                    sprintf(tbuf, "%s %s", LOC(teacher->faction->locale,
                        parameters[P_TEMP]), token);
                    uid = tbuf;
                }
                else {
                    uid = token;
                }
                ADDMSG(&teacher->faction->msgs, msg_feedback(teacher, ord, "unitnotfound_id",
                    "id", uid));

                parser_popstate();
                continue;
            }

            feedback = teacher->faction == scholar->faction
                || alliedunit(scholar, teacher->faction, HELP_GUARD);

            /* Neuen Befehl zusammenbauen. TEMP-Einheiten werden automatisch in
             * ihre neuen Nummern uebersetzt. */
            if (zOrder[0]) {
                strncat(zOrder, " ", sz - 1);
                --sz;
            }
            sz -= str_strlcpy(zOrder + 4096 - sz, itoa36(scholar->no), sz);

            if (getkeyword(scholar->thisorder) != K_STUDY) {
                ADDMSG(&teacher->faction->msgs,
                    msg_feedback(teacher, ord, "teach_nolearn", "student", scholar));
                continue;
            }

            /* Input ist nun von student->thisorder !! */
            parser_pushstate();
            init_order(scholar->thisorder, scholar->faction->locale);
            sk = getskill(scholar->faction->locale);
            parser_popstate();

            if (sk == NOSKILL) {
                ADDMSG(&teacher->faction->msgs,
                    msg_feedback(teacher, ord, "teach_nolearn", "student", scholar));
                continue;
            }

            if (effskill_study(scholar, sk) > effskill_study(teacher, sk)
                - TEACHDIFFERENCE) {
                if (feedback) {
                    ADDMSG(&teacher->faction->msgs, msg_feedback(teacher, ord, "teach_asgood",
                        "student", scholar));
                }
                continue;
            }
            if (sk == SK_MAGIC) {
                /* ist der Magier schon spezialisiert, so versteht er nur noch
                 * Lehrer seines Gebietes */
                magic_t mage2 = unit_get_magic(scholar);
                if (mage2 != M_GRAY) {
                    magic_t mage1 = unit_get_magic(teacher);
                    if (mage1 != mage2) {
                        if (feedback) {
                            ADDMSG(&teacher->faction->msgs, msg_feedback(teacher, ord,
                                "error_different_magic", "target", scholar));
                        }
                        continue;
                    }
                }
            }
            sk_academy = sk;
            teaching -= teach_unit(teacher, scholar, teaching, sk, false, &academy_students);
        }
        new_order = create_order(K_TEACH, teacher->faction->locale, "%s", zOrder);
        replace_order(&teacher->orders, ord, new_order);
        free_order(new_order);      /* parse_order & set_order have each increased the refcount */
    }
    if (academy_students > 0 && sk_academy!=NOSKILL) {
        academy_teaching_bonus(teacher, sk_academy, academy_students);
    }
    init_order_depr(NULL);
    return 0;
}