static void test_attrib_nexttype(CuTest * tc) { attrib_type at_foo = { "foo" }; attrib_type at_bar = { "bar" }; attrib *a, *alist = 0; CuAssertPtrNotNull(tc, (a = a_new(&at_foo))); CuAssertPtrEquals(tc, 0, a->nexttype); CuAssertPtrEquals(tc, a, a_add(&alist, a)); CuAssertPtrEquals(tc, 0, alist->nexttype); CuAssertPtrNotNull(tc, a_add(&alist, a_new(&at_foo))); CuAssertPtrEquals(tc, 0, alist->nexttype); CuAssertPtrNotNull(tc, (a = a_add(&alist, a_new(&at_bar)))); CuAssertPtrEquals(tc, a, alist->nexttype); CuAssertPtrEquals(tc, 0, a->nexttype); a_remove(&alist, alist); CuAssertPtrEquals(tc, a, alist->nexttype); CuAssertPtrNotNull(tc, (a = a_add(&alist, a_new(&at_bar)))); a_remove(&alist, alist->nexttype); CuAssertPtrEquals(tc, a, alist->nexttype); a_removeall(&alist, &at_foo); a_removeall(&alist, &at_bar); }
static int do_potion(unit * u, region *r, const potion_type * ptype, int amount) { if (ptype == oldpotiontype[P_LIFE]) { int holz = 0; static int tree_type = -1; static int tree_count = -1; if (tree_type < 0) { tree_type = get_param_int(global.parameters, "rules.magic.wol_type", 1); tree_count = get_param_int(global.parameters, "rules.magic.wol_effect", 10); } /* mallorn is required to make mallorn forests, wood for regular ones */ if (fval(r, RF_MALLORN)) { holz = use_pooled(u, rt_find("mallorn"), GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, tree_count * amount); } else { holz = use_pooled(u, rt_find("log"), GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, tree_count * amount); } if (r->land == 0) holz = 0; if (holz < tree_count * amount) { int x = holz / tree_count; if (holz % tree_count) ++x; if (x < amount) amount = x; } rsettrees(r, tree_type, rtrees(r, tree_type) + holz); ADDMSG(&u->faction->msgs, msg_message("growtree_effect", "mage amount", u, holz)); } else if (ptype == oldpotiontype[P_HEILWASSER]) { u->hp = _min(unit_max_hp(u) * u->number, u->hp + 400 * amount); } else if (ptype == oldpotiontype[P_PEOPLE]) { attrib *a = (attrib *) a_find(r->attribs, &at_peasantluck); if (!a) a = a_add(&r->attribs, a_new(&at_peasantluck)); a->data.i += amount; } else if (ptype == oldpotiontype[P_HORSE]) { attrib *a = (attrib *) a_find(r->attribs, &at_horseluck); if (!a) a = a_add(&r->attribs, a_new(&at_horseluck)); a->data.i += amount; } else if (ptype == oldpotiontype[P_WAHRHEIT]) { fset(u, UFL_DISBELIEVES); amount = 1; } else if (ptype == oldpotiontype[P_MACHT]) { /* Verfünffacht die HP von max. 10 Personen in der Einheit */ u->hp += _min(u->number, 10 * amount) * unit_max_hp(u) * 4; } else { change_effect(u, ptype, 10 * amount); } return amount; }
static void test_attrib_remove(CuTest * tc) { attrib_type at_foo = { "foo" }; attrib *a, *alist = 0; CuAssertPtrNotNull(tc, a_add(&alist, a_new(&at_foo))); CuAssertPtrNotNull(tc, a = a_add(&alist, a_new(&at_foo))); CuAssertIntEquals(tc, 1, a_remove(&alist, a)); CuAssertPtrNotNull(tc, alist); CuAssertIntEquals(tc, 1, a_remove(&alist, alist)); CuAssertPtrEquals(tc, 0, alist); }
void warden_add_give(unit * src, unit * u, const item_type * itype, int n) { attrib *aw = a_find(u->attribs, &at_warden); museumgiveback *gb = NULL; museumgivebackcookie *gbc; attrib *a; /* has the giver a cookie corresponding to the warden */ for (a = a_find(src->attribs, &at_museumgivebackcookie); a && a->type == &at_museumgivebackcookie; a = a->next) { if (((museumgivebackcookie *)(a->data.v))->warden_no == u->no) break; } /* if not give it one */ if (a == NULL || a->type != &at_museumgivebackcookie) { a = a_add(&src->attribs, a_new(&at_museumgivebackcookie)); gbc = (museumgivebackcookie *)a->data.v; gbc->warden_no = u->no; gbc->cookie = aw->data.i; assert(aw->data.i < INT_MAX); aw->data.i++; } else { gbc = (museumgivebackcookie *)(a->data.v); } /* now we search for the warden's corresponding item list */ for (a = a_find(u->attribs, &at_museumgiveback); a && a->type == &at_museumgiveback; a = a->next) { gb = (museumgiveback *)a->data.v; if (gb->cookie == gbc->cookie) { break; } } /* if there's none, give it one */ if (!gb) { a = a_add(&u->attribs, a_new(&at_museumgiveback)); gb = (museumgiveback *)a->data.v; gb->cookie = gbc->cookie; } /* now register the items */ i_change(&gb->items, itype, n); /* done */ /* this has a caveat: If the src-unit is destroyed while inside * the museum, the corresponding itemlist of the warden will never * be removed. to circumvent that in a generic way will be extremly * difficult. */ }
static void test_attrib_removeall(CuTest * tc) { const attrib_type at_foo = { "foo" }; const attrib_type at_bar = { "bar" }; attrib *alist = 0, *a; a_add(&alist, a_new(&at_foo)); a = a_add(&alist, a_new(&at_bar)); a_add(&alist, a_new(&at_foo)); a_removeall(&alist, &at_foo); CuAssertPtrEquals(tc, a, alist); CuAssertPtrEquals(tc, 0, alist->next); a_add(&alist, a_new(&at_bar)); a_add(&alist, a_new(&at_foo)); a_removeall(&alist, NULL); CuAssertPtrEquals(tc, 0, alist); }
int change_effect(unit * u, const potion_type * effect, int delta) { if (delta != 0) { attrib *a = a_find(u->attribs, &at_effect); effect_data *data = NULL; while (a && a->type == &at_effect) { data = (effect_data *) a->data.v; if (data->type == effect) { if (data->value + delta == 0) { a_remove(&u->attribs, a); return 0; } else { data->value += delta; return data->value; } } a = a->next; } a = a_add(&u->attribs, a_new(&at_effect)); data = (effect_data *) a->data.v; data->type = effect; data->value = delta; return data->value; } log_error("change effect with delta==0 for unit %s\n", itoa36(u->no)); return 0; }
static int use_speedsail(struct unit *u, const struct item_type *itype, int amount, struct order *ord) { struct plane *p = rplane(u->region); unused_arg(amount); unused_arg(itype); if (p != NULL) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "use_realworld_only", "")); } else { if (u->ship) { attrib *a = a_find(u->ship->attribs, &at_speedup); if (a == NULL) { a = a_add(&u->ship->attribs, a_new(&at_speedup)); a->data.sa[0] = 50; /* speed */ a->data.sa[1] = 50; /* decay */ ADDMSG(&u->faction->msgs, msg_message("use_speedsail", "unit", u)); /* Ticket abziehen */ i_change(&u->items, itype, -1); return 0; } else { cmistake(u, ord, 211, MSG_EVENT); } } else { cmistake(u, ord, 144, MSG_EVENT); } } return EUNUSABLE; }
void set_group(struct unit *u, struct group *g) { attrib *a = NULL; if (fval(u, UFL_GROUP)) { a = a_find(u->attribs, &at_group); } if (a) { group *og = (group *)a->data.v; if (og == g) return; --og->members; } if (g) { if (!a) { a = a_add(&u->attribs, a_new(&at_group)); fset(u, UFL_GROUP); } a->data.v = g; g->members++; } else if (a) { a_remove(&u->attribs, a); freset(u, UFL_GROUP); } }
static HParseResult* parse_epsilon(void* env, HParseState* state) { (void)env; HParseResult* res = a_new(HParseResult, 1); res->ast = NULL; res->arena = state->arena; return res; }
static fighter *summon_allies(const fighter *fi, const race *rc, int number) { attrib *a; unit *mage = fi->unit; side *si = fi->side; battle *b = si->battle; region *r = b->region; message *msg; unit *u = create_unit(r, mage->faction, number, rc, 0, NULL, mage); leave(u, true); unit_setstatus(u, ST_FIGHT); u->hp = u->number * unit_max_hp(u); if (mage->flags & UFL_ANON_FACTION) { u->flags |= UFL_ANON_FACTION; } a = a_new(&at_unitdissolve); a->data.ca[0] = 0; a->data.ca[1] = 100; a_add(&u->attribs, a); msg = msg_message("sp_wolfhowl_effect", "mage amount race", mage, u->number, rc); message_all(b, msg); msg_release(msg); return make_fighter(b, u, si, is_attacker(fi)); }
void set_movement(attrib ** alist, int type) { attrib *a = a_find(*alist, &at_movement); if (a == NULL) a = a_add(alist, a_new(&at_movement)); a->data.i |= type; }
int sp_shadowcall(struct castorder * co) { fighter * fi = co->magician.fig; int level = co->level; double power = co->force; battle *b = fi->side->battle; region *r = b->region; unit *mage = fi->unit; attrib *a; int force = (int)(get_force(power, 3) / 2); unit *u; const char *races[3] = { "shadowbat", "nightmare", "vampunicorn" }; const race *rc = rc_find(races[rng_int() % 3]); message *msg; u = create_unit(r, mage->faction, force, rc, 0, NULL, mage); setstatus(u, ST_FIGHT); set_level(u, SK_WEAPONLESS, (int)(power / 2)); set_level(u, SK_STAMINA, (int)(power / 2)); u->hp = u->number * unit_max_hp(u); a = a_new(&at_unitdissolve); a->data.ca[0] = 0; a->data.ca[1] = 100; a_add(&u->attribs, a); make_fighter(b, u, fi->side, is_attacker(fi)); msg = msg_message("sp_shadowcall_effect", "mage amount race", mage, u->number, u_race(u)); message_all(b, msg); msg_release(msg); return level; }
void usetpotionuse(unit * u, const potion_type * ptype) { attrib *a = a_find(u->attribs, &at_potionuser); if (!a) a = a_add(&u->attribs, a_new(&at_potionuser)); a->data.v = (void *)ptype; }
/* Legt eine neue Verzauberung an. Sollte es schon einen Zauber * dieses Typs geben, gibt es den bestehenden zurück. */ static curse *make_curse(unit * mage, attrib ** ap, const curse_type * ct, float vigour, int duration, float effect, int men) { curse *c; attrib *a; a = a_new(&at_curse); a_add(ap, a); c = (curse *) a->data.v; c->type = ct; c->flags = 0; c->vigour = vigour; c->duration = duration; c->effect = effect; c->magician = mage; c->no = newunitid(); chash(c); switch (c->type->typ) { case CURSETYP_NORM: break; case CURSETYP_UNIT: { c->data.i = men; break; } } return c; }
attrib *make_reduceproduction(int percent, int time) { attrib *a = a_new(&at_reduceproduction); a->data.sa[0] = (short)percent; a->data.sa[1] = (short)time; return a; }
// short-hand for caching parse results (left recursion case) static HParserCacheValue *cached_lr(HParseState *state, HLeftRec *lr) { HParserCacheValue *ret = a_new(HParserCacheValue, 1); ret->value_type = PC_LEFT; ret->left = lr; ret->input_stream = state->input_stream; return ret; }
// short-hand for creating cache values (regular case) static HParserCacheValue * cached_result(HParseState *state, HParseResult *result) { HParserCacheValue *ret = a_new(HParserCacheValue, 1); ret->value_type = PC_RIGHT; ret->right = result; ret->input_stream = state->input_stream; return ret; }
faction *gm_addfaction(const char *email, plane * p, region * r) { attrib *a; unit *u; faction *f = calloc(1, sizeof(faction)); assert(p != NULL); /* GM faction */ a_add(&f->attribs, make_key(atoi36("quest"))); f->banner = _strdup("quest faction"); f->name = _strdup("quest faction"); f->passw = _strdup(itoa36(rng_int())); if (set_email(&f->email, email) != 0) { log_error("Invalid email address for faction %s: %s\n", itoa36(f->no), email); } f->race = new_race[RC_TEMPLATE]; f->age = 0; f->lastorders = turn; f->alive = true; f->locale = default_locale; f->options = want(O_COMPRESS) | want(O_REPORT) | want(O_COMPUTER) | want(O_ADRESSEN); { faction *xist; int id = atoi36("gm00") - 1; do { xist = findfaction(++id); } while (xist); f->no = id; addlist(&factions, f); fhash(f); } /* generic permissions */ a = a_add(&f->attribs, a_new(&at_permissions)); if (a) { attrib *ap = (attrib *) a->data.v; const char *keys[] = { "gmterf", "gmtele", "gmgive", "gmskil", "gmtake", "gmmsgr", "gmmsgu", "gmgate", 0 }; const char **key_p = keys; while (*key_p) { add_key(&ap, atoi36(*key_p)); ++key_p; } a_add(&ap, make_atgmcreate(resource2item(r_silver))); a->data.v = ap; } /* one initial unit */ u = create_unit(r, f, 1, new_race[RC_TEMPLATE], 1, "quest master", NULL); u->irace = new_race[RC_GNOME]; return f; }
void usetcontact(unit * u, const unit * u2) { attrib *a = a_find(u->attribs, &at_contact); while (a && a->type == &at_contact && a->data.v != u2) a = a->next; if (a && a->type == &at_contact) return; a_add(&u->attribs, a_new(&at_contact))->data.v = (void *)u2; }
static HParseResult* parse_end(void *env, HParseState *state) { if (state->input_stream.index == state->input_stream.length) { HParseResult *ret = a_new(HParseResult, 1); ret->ast = NULL; return ret; } else { return NULL; } }
static HParseResult* parse_ignore(void* env, HParseState* state) { HParseResult *res0 = h_do_parse((HParser*)env, state); if (!res0) return NULL; HParseResult *res = a_new(HParseResult, 1); res->ast = NULL; res->arena = state->arena; return res; }
void building_addaction(building * b, const char *fname, const char *param) { attrib *a = a_add(&b->attribs, a_new(&at_building_action)); building_action *data = (building_action *)a->data.v; data->fname = _strdup(fname); if (param) { data->param = _strdup(param); } }
struct attrib *object_create(const char *name, object_type type, variant value) { attrib *a = a_new(&at_object); object_data *data = (object_data *) a->data.v; data->name = _strdup(name); object_set(a, type, value); return a; }
static void make_wormhole(const building_type * bt_wormhole, region * r1, region * r2) { building *b1 = new_building(bt_wormhole, r1, default_locale); building *b2 = new_building(bt_wormhole, r2, default_locale); attrib *a1 = a_add(&b1->attribs, a_new(&at_wormhole)); attrib *a2 = a_add(&b2->attribs, a_new(&at_wormhole)); wormhole_data *d1 = (wormhole_data *)a1->data.v; wormhole_data *d2 = (wormhole_data *)a2->data.v; d1->entry = b1; d2->entry = b2; d1->exit = b2->region; d2->exit = b1->region; b1->size = bt_wormhole->maxsize; b2->size = bt_wormhole->maxsize; ADDMSG(&r1->msgs, msg_message("wormhole_appear", "region", r1)); ADDMSG(&r2->msgs, msg_message("wormhole_appear", "region", r2)); }
static attrib *mk_piracy(const faction * pirate, const faction * target, direction_t target_dir) { attrib *a = a_new(&at_piracy_direction); piracy_data *data = a->data.v; data->pirate = pirate; data->target = target; data->dir = target_dir; return a; }
static HParseResult* parse_optional(void* env, HParseState* state) { HInputStream bak = state->input_stream; HParseResult *res0 = h_do_parse((HParser*)env, state); if (res0) return res0; state->input_stream = bak; HParsedToken *ast = a_new(HParsedToken, 1); ast->token_type = TT_NONE; return make_result(state->arena, ast); }
static HParseResult* parse_bits(void* env, HParseState *state) { struct bits_env *env_ = env; HParsedToken *result = a_new(HParsedToken, 1); result->token_type = (env_->signedp ? TT_SINT : TT_UINT); if (env_->signedp) result->sint = h_read_bits(&state->input_stream, env_->length, true); else result->uint = h_read_bits(&state->input_stream, env_->length, false); return make_result(state, result); }
static attrib *make_potiondelay(unit * u, const potion_type * ptype, int amount) { attrib *a = a_new(&at_potiondelay); potiondelay *pd = (potiondelay *) a->data.v; pd->u = u; pd->r = u->region; pd->ptype = ptype; pd->amount = amount; return a; }
static void test_upgrade_dict(CuTest *tc) { attrib *a; a = a_new(&at_dict); dict_set(a, "embassy_muschel", 42); CuAssertPtrNotNull(tc, a->type->upgrade); a->type->upgrade(&a, a); CuAssertIntEquals(tc, 42, key_get(a, atoi36("mupL"))); a_removeall(&a, NULL); }
void set_prefix(attrib ** ap, const char *str) { attrib *a = a_find(*ap, &at_raceprefix); if (a == NULL) { a = a_add(ap, a_new(&at_raceprefix)); } else { free(a->data.v); } assert(a->type == &at_raceprefix); a->data.v = _strdup(str); }