void test_upkeep_from_pool(CuTest * tc) { region *r; unit *u1, *u2; const item_type *i_silver; test_cleanup(); test_create_world(); i_silver = it_find("money"); assert(i_silver); r = findregion(0, 0); u1 = test_create_unit(test_create_faction(test_create_race("human")), r); assert(u1); u2 = test_create_unit(u1->faction, r); assert(r && u1 && u2); set_param(&global.parameters, "rules.food.flags", "0"); i_change(&u1->items, i_silver, 30); get_food(r); CuAssertIntEquals(tc, 10, i_get(u1->items, i_silver)); CuAssertIntEquals(tc, 0, fval(u1, UFL_HUNGER)); CuAssertIntEquals(tc, 0, fval(u2, UFL_HUNGER)); get_food(r); CuAssertIntEquals(tc, 0, i_get(u1->items, i_silver)); CuAssertIntEquals(tc, 0, fval(u1, UFL_HUNGER)); CuAssertIntEquals(tc, UFL_HUNGER, fval(u2, UFL_HUNGER)); test_cleanup(); }
void test_upkeep_default(CuTest * tc) { region *r; unit *u1, *u2; faction *f1, *f2; const item_type *i_silver; test_cleanup(); test_create_world(); i_silver = it_find("money"); assert(i_silver); r = findregion(0, 0); f1 = test_create_faction(test_create_race("human")); f2 = test_create_faction(test_create_race("human")); assert(f1 && f2); u1 = test_create_unit(f1, r); u2 = test_create_unit(f2, r); assert(r && u1 && u2); set_param(&global.parameters, "rules.food.flags", "0"); i_change(&u1->items, i_silver, 20); get_food(r); // since u1 and u2 are not allied, u1 should not help u2 with upkeep CuAssertIntEquals(tc, 10, i_get(u1->items, i_silver)); CuAssertIntEquals(tc, 0, fval(u1, UFL_HUNGER)); CuAssertIntEquals(tc, UFL_HUNGER, fval(u2, UFL_HUNGER)); test_cleanup(); }
static const terrain_type *chaosterrain(void) { static const terrain_type **types; static int numtypes; if (numtypes == 0) { const terrain_type *terrain; for (terrain = terrains(); terrain != NULL; terrain = terrain->next) { if (fval(terrain, LAND_REGION) && terrain->herbs) { ++numtypes; } } if (numtypes > 0) { types = malloc(sizeof(terrain_type *) * numtypes); numtypes = 0; for (terrain = terrains(); terrain != NULL; terrain = terrain->next) { if (fval(terrain, LAND_REGION) && terrain->herbs) { types[numtypes++] = terrain; } } } } if (numtypes > 0) { return types[rng_int() % numtypes]; } return NULL; }
int get_modifier(const unit * u, skill_t sk, int level, const region * r, bool noitem) { int bskill = level; int skill = bskill; if (r && sk == SK_STEALTH) { plane *pl = rplane(r); if (pl && fval(pl, PFL_NOSTEALTH)) { return 0; } } skill += rc_skillmod(u_race(u), r, sk); skill += att_modification(u, sk); if (!noitem) { skill = item_modification(u, sk, skill); } skill = skillmod(u->attribs, u, r, sk, skill, SMF_ALWAYS); #ifdef HUNGER_REDUCES_SKILL if (fval(u, UFL_HUNGER)) { skill = skill / 2; } #endif return skill - bskill; }
void encounters(void) { region *r; for (r = regions; r; r = r->next) { if (fval(r->terrain, LAND_REGION) && fval(r, RF_ENCOUNTER)) { int c = 0; unit *u; for (u = r->units; u; u = u->next) { c += u->number; } if (c > 0) { int i = 0; int n = rng_int() % c; for (u = r->units; u; u = u->next) { if (i + u->number > n) break; i += u->number; } assert(u && u->number); encounter(r, u); } } } }
void randomevents(void) { region *r; faction *monsters = get_monsters(); icebergs(); godcurse(); orc_growth(); demon_skillchanges(); volcano_update(); /* Monumente zerfallen, Schiffe verfaulen */ for (r = regions; r; r = r->next) { building **blist = &r->buildings; while (*blist) { building *b = *blist; if (fval(b->type, BTF_DECAY) && !building_owner(b)) { b->size -= _max(1, (b->size * 20) / 100); if (b->size == 0) { remove_building(blist, r->buildings); } } if (*blist == b) blist = &b->next; } } /* monster-einheiten desertieren */ if (monsters) { for (r = regions; r; r = r->next) { unit *u; for (u = r->units; u; u = u->next) { if (u->faction && !is_monsters(u->faction) && (u_race(u)->flags & RCF_DESERT)) { if (fval(u, UFL_ISNEW)) continue; if (rng_int() % 100 < 5) { ADDMSG(&u->faction->msgs, msg_message("desertion", "unit region", u, r)); u_setfaction(u, monsters); } } } } } chaos_update(); #ifdef HERBS_ROT rotting_herbs(); #endif dissolve_units(); }
bool path_exists(region * start, const region * target, int maxlen, bool(*allowed) (const region *, const region *)) { assert((!fval(start, RF_MARK) && !fval(target, RF_MARK)) || !"Some Algorithm did not clear its RF_MARKs!"); if (start == target) return true; if (internal_path_find(start, target, maxlen, allowed) != NULL) return true; return false; }
guard_t can_start_guarding(const unit * u) { if (u->status >= ST_FLEE || fval(u, UFL_FLEEING)) return E_GUARD_FLEEING; /* Monster der Monsterpartei duerfen immer bewachen */ if (is_monsters(u->faction) || fval(u_race(u), RCF_UNARMEDGUARD)) return E_GUARD_OK; if (!armedmen(u, true)) return E_GUARD_UNARMED; if (IsImmune(u->faction)) return E_GUARD_NEWBIE; return E_GUARD_OK; }
void get_onesided_intervals(const dvector& _left_bd, const dvector& _right_bd, dmatrix& ms, const dvector& xs, const dvector& siglevel, const int& level_index, int index) { dvector& left_bd=(dvector&) _left_bd; dvector& right_bd=(dvector&) _right_bd; dvector& fval=ms(index); int lb=fval.indexmin()+1; int ub=fval.indexmax(); double xdiff=0.0; double isum=0; double tmpsum=0.0; int ii; for (ii=lb+1;ii<=ub;ii++) { tmpsum+=fval(ii)*(xs(ii)-xs(ii-1)); } isum=0.0; for (ii=lb+1;ii<=ub;ii++) { xdiff=xs(ii)-xs(ii-1); double incr=fval(ii)*xdiff/tmpsum; double fdiff = 1.-siglevel(level_index) - isum; if ( incr >= fdiff) { double delta=fdiff/incr; left_bd(level_index)=xs(ii)+delta*xdiff; break; } isum+=incr; } //cout << "tmpsum = " << tmpsum << endl; isum=0; for (ii=ub-1;ii>=lb;ii--) { xdiff=xs(ii+1)-xs(ii); double incr=fval(ii)*xdiff/tmpsum; double fdiff = 1.-siglevel(level_index) - isum; if ( incr >= fdiff) { double delta=fdiff/incr; right_bd(level_index)=xs(ii)+delta*xdiff; break; } isum+=incr; } }
bool check_leuchtturm(region * r, faction * f) { attrib *a; if (!fval(r->terrain, SEA_REGION)) { return false; } for (a = a_find(r->attribs, &at_lighthouse); a && a->type == &at_lighthouse; a = a->next) { building *b = (building *)a->data.v; assert(is_building_type(b->type, "lighthouse")); if (fval(b, BLD_MAINTAINED) && b->size >= 10) { int maxd = (int)log10(b->size) + 1; if (skill_enabled(SK_PERCEPTION) && f) { region *r2 = b->region; unit *u; int c = 0; int d = 0; for (u = r2->units; u; u = u->next) { if (u->building == b) { c += u->number; if (c > buildingcapacity(b)) break; if (u->faction == f) { if (!d) d = distance(r, r2); if (maxd < d) break; if (effskill(u, SK_PERCEPTION, 0) >= d * 3) return true; } } else if (c) break; /* first unit that's no longer in the house ends the search */ } } else { /* E3A rule: no perception req'd */ return true; } } } return false; }
static void godcurse(void) { region *r; for (r = regions; r; r = r->next) { if (is_cursed(r->attribs, C_CURSED_BY_THE_GODS, 0)) { unit *u; for (u = r->units; u; u = u->next) { skill *sv = u->skills; while (sv != u->skills + u->skill_size) { int weeks = 1 + rng_int() % 3; reduce_skill(u, sv, weeks); ++sv; } } if (fval(r->terrain, SEA_REGION)) { ship *sh; for (sh = r->ships; sh;) { ship *shn = sh->next; double dmg = config_get_flt("rules.ship.damage.godcurse", 0.1); damage_ship(sh, dmg); if (sh->damage >= sh->size * DAMAGE_SCALE) { unit *u = ship_owner(sh); if (u) ADDMSG(&u->faction->msgs, msg_message("godcurse_destroy_ship", "ship", sh)); remove_ship(&sh->region->ships, sh); } sh = shn; } } } } }
/** ** 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); } } }
struct building *inside_building(const struct unit *u) { if (u->building == NULL) return NULL; if (!fval(u->building, BLD_WORKING)) { /* Unterhalt nicht bezahlt */ return NULL; } else if (u->building->size < u->building->type->maxsize) { /* Gebäude noch nicht fertig */ return NULL; } else { int p = 0, cap = buildingcapacity(u->building); const unit *u2; for (u2 = u->region->units; u2; u2 = u2->next) { if (u2->building == u->building) { p += u2->number; if (u2 == u) { if (p <= cap) return u->building; return NULL; } if (p > cap) return NULL; } } } return NULL; }
std::unique_ptr<Value> FunctionValueNode::getValue(std::unique_ptr<Value> val) const { switch (val->getType()) { case Value::String: { StringValue& sval(static_cast<StringValue&>(*val)); if (_function == LOWERCASE) { return std::unique_ptr<Value>(new StringValue( vespalib::LowerCase::convert(sval.getValue()))); } else if (_function == HASH) { return std::unique_ptr<Value>(new IntegerValue( hash(sval.getValue().c_str(), sval.getValue().size()), false)); } break; } case Value::Float: { FloatValue& fval(static_cast<FloatValue&>(*val)); if (_function == HASH) { FloatValue::ValueType ffval = fval.getValue(); return std::unique_ptr<Value>(new IntegerValue( hash(&ffval, sizeof(ffval)), false)); } else if (_function == ABS) { FloatValue::ValueType ffval = fval.getValue(); if (ffval < 0) ffval *= -1; return std::unique_ptr<Value>(new FloatValue(ffval)); } break; } case Value::Integer: { IntegerValue& ival(static_cast<IntegerValue&>(*val)); if (_function == HASH) { IntegerValue::ValueType iival = ival.getValue(); return std::unique_ptr<Value>(new IntegerValue( hash(&iival, sizeof(iival)), false)); } else if (_function == ABS) { IntegerValue::ValueType iival = ival.getValue(); if (iival < 0) iival *= -1; return std::unique_ptr<Value>(new IntegerValue(iival, false)); } break; } case Value::Bucket: { throw ParsingFailedException( "No functioncalls are allowed on value of type bucket", VESPA_STRLOC); break; } case Value::Array: break; case Value::Struct: break; case Value::Invalid: break; case Value::Null: break; } return std::unique_ptr<Value>(new InvalidValue); }
static quicklist * get_island(region * root) { quicklist * ql, *result = 0; int qi = 0; fset(root, RF_MARK); ql_push(&result, root); for (ql = result, qi = 0; ql; ql_advance(&ql, &qi, 1)) { int dir; region *r = (region *)ql_get(ql, qi); region * next[MAXDIRECTIONS]; get_neighbours(r, next); for (dir = 0; dir != MAXDIRECTIONS; ++dir) { region *rn = next[dir]; if (rn != NULL && rn->land && !fval(rn, RF_MARK)) { fset(rn, RF_MARK); ql_push(&result, rn); } } } for (ql = result, qi = 0; ql; ql_advance(&ql, &qi, 1)) { region *r = (region *)ql_get(ql, qi); freset(r, RF_MARK); } return result; }
static int scareaway(region * r, int anzahl) { int n, p, diff = 0, emigrants[MAXDIRECTIONS]; direction_t d; anzahl = _min(_max(1, anzahl), rpeasants(r)); /* Wandern am Ende der Woche (normal) oder wegen Monster. Die * Wanderung wird erst am Ende von demographics () ausgefuehrt. * emigrants[] ist local, weil r->newpeasants durch die Monster * vielleicht schon hochgezaehlt worden ist. */ for (d = 0; d != MAXDIRECTIONS; d++) emigrants[d] = 0; p = rpeasants(r); assert(p >= 0 && anzahl >= 0); for (n = _min(p, anzahl); n; n--) { direction_t dir = (direction_t) (rng_int() % MAXDIRECTIONS); region *rc = rconnect(r, dir); if (rc && fval(rc->terrain, LAND_REGION)) { ++diff; rc->land->newpeasants++; emigrants[dir]++; } } rsetpeasants(r, p - diff); assert(p >= diff); return diff; }
void GLNode::onDraw(Mat4 &transform, uint32_t flags) { JSContext *cx = ScriptingCore::getInstance()->getGlobalContext(); js_type_class_t *typeClass = js_get_type_from_native<cocos2d::GLNode>(this); JS::RootedObject jsObj(cx, jsb_ref_get_or_create_jsobject(cx, this, typeClass, "cocos2d::GLNode")); if (jsObj.get()) { bool found = false; JSB_AUTOCOMPARTMENT_WITH_GLOBAL_OBJCET JS_HasProperty(cx, jsObj, "draw", &found); if (found) { auto director = Director::getInstance(); director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, transform); JS::RootedValue rval(cx); JS::RootedValue fval(cx); JS_GetProperty(cx, jsObj, "draw", &fval); JS_CallFunctionValue(cx, jsObj, fval, JS::HandleValueArray::empty(), &rval); director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); } } }
static void rotting_herbs(void) { region *r; int rule_rot = config_get_int("rules.economy.herbrot", HERBROTCHANCE); if (rule_rot == 0) return; for (r = regions; r; r = r->next) { unit *u; for (u = r->units; u; u = u->next) { const struct item_type *it_bag = it_find("magicherbbag"); item **itmp = &u->items; int rot_chance = rule_rot; if (it_bag && *i_find(itmp, it_bag)) { rot_chance = (rot_chance * 2) / 5; } while (*itmp) { item *itm = *itmp; int n = itm->number; double k = n * rot_chance / 100.0; if (fval(itm->type, ITF_HERB)) { double nv = normalvariate(k, k / 4); int inv = (int)nv; int delta = _min(n, inv); if (!i_change(itmp, itm->type, -delta)) { continue; } } itmp = &itm->next; } } } }
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); } }
/* Magier weicht dem Kampf aus. Wenn er sich bewegen kann, zieht er in * eine Nachbarregion, wobei ein NACH berücksichtigt wird. Ansonsten * bleibt er stehen und nimmt nicht weiter am Kampf teil. */ int sp_denyattack(struct castorder * co) { fighter * fi = co->magician.fig; int level = co->level; const spell * sp = co->sp; battle *b = fi->side->battle; unit *mage = fi->unit; region *r = b->region; message *m; /* Fliehende Einheiten verlassen auf jeden Fall Gebäude und Schiffe. */ if (!fval(r->terrain, SEA_REGION)) { leave(mage, false); } /* und bewachen nicht */ setguard(mage, GUARD_NONE); /* irgendwie den langen befehl sperren */ /* fset(fi, FIG_ATTACKED); */ /* wir tun so, als wäre die Person geflohen */ fset(fi, FIG_NOLOOT); fi->run.hp = mage->hp; fi->run.number = mage->number; /* fighter leeren */ rmfighter(fi, mage->number); m = msg_message("cast_escape_effect", "mage spell", fi->unit, sp); message_all(b, m); msg_release(m); return level; }
bool AddonWrapper<Base>::set(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id, JS::HandleValue v, JS::HandleValue receiver, JS::ObjectOpResult& result) const { Rooted<JSPropertyDescriptor> desc(cx); if (!InterposeProperty(cx, wrapper, nullptr, id, &desc)) return false; if (!desc.object()) return Base::set(cx, wrapper, id, v, receiver, result); if (desc.setter()) { MOZ_ASSERT(desc.hasSetterObject()); JS::AutoValueVector args(cx); if (!args.append(v)) return false; RootedValue fval(cx, ObjectValue(*desc.setterObject())); RootedValue ignored(cx); if (!JS::Call(cx, receiver, fval, args, &ignored)) return false; return result.succeed(); } return result.failCantSetInterposed(); }
unit *is_guarded(region * r, unit * u) { unit *u2; bool noguards = true; if (!fval(r, RF_GUARDED)) { return NULL; } /* at this point, u2 is the last unit we tested to * be a guard (and failed), or NULL * i is the position of the first free slot in the cache */ for (u2 = r->units; u2; u2 = u2->next) { if (is_guardian_r(u2)) { noguards = false; if (is_guardian_u(u2, u)) { /* u2 is our guard. stop processing (we might have to go further next time) */ return u2; } } } if (noguards) { /* you are mistaken, sir. there are no guards in these lands */ freset(r, RF_GUARDED); } return NULL; }
static void melt_iceberg(region * r) { attrib *a; unit *u; for (u = r->units; u; u = u->next) freset(u->faction, FFL_SELECT); for (u = r->units; u; u = u->next) if (!fval(u->faction, FFL_SELECT)) { fset(u->faction, FFL_SELECT); ADDMSG(&u->faction->msgs, msg_message("iceberg_melt", "region", r)); } /* driftrichtung löschen */ a = a_find(r->attribs, &at_iceberg); if (a) a_remove(&r->attribs, a); /* Gebäude löschen */ while (r->buildings) { remove_building(&r->buildings, r->buildings); } /* in Ozean wandeln */ terraform_region(r, newterrain(T_OCEAN)); /* Einheiten, die nicht schwimmen können oder in Schiffen sind, * ertrinken */ drown(r); }
int update_nmrs(void) { int i, newplayers = 0; faction *f; int turn = global.data_turn; if (nmrs == NULL) nmrs = malloc(sizeof(int) * (NMRTimeout() + 1)); for (i = 0; i <= NMRTimeout(); ++i) { nmrs[i] = 0; } for (f = factions; f; f = f->next) { if (fval(f, FFL_ISNEW)) { ++newplayers; } else if (!is_monsters(f) && f->alive) { int nmr = turn - f->lastorders + 1; if (nmr < 0 || nmr > NMRTimeout()) { log_error("faction %s has %d NMRS\n", factionid(f), nmr); nmr = _max(0, nmr); nmr = _min(nmr, NMRTimeout()); } ++nmrs[nmr]; } } return newplayers; }
void drown(region * r) { if (fval(r->terrain, SEA_REGION)) { unit **up = up = &r->units; while (*up) { unit *u = *up; int amphibian_level = 0; if (u->ship || u_race(u) == get_race(RC_SPELL) || u->number == 0) { up = &u->next; continue; } if (amphibian_level) { int dead = damage_unit(u, "5d1", false, false); if (dead) { ADDMSG(&u->faction->msgs, msg_message("drown_amphibian_dead", "amount unit region", dead, u, r)); } else { ADDMSG(&u->faction->msgs, msg_message("drown_amphibian_nodead", "unit region", u, r)); } } else if (!(canswim(u) || canfly(u))) { scale_number(u, 0); ADDMSG(&u->faction->msgs, msg_message("drown", "unit region", u, r)); } if (*up == u) up = &u->next; } remove_empty_units_in_region(r); } }
unit *utarget(const unit * u) { attrib *a; if (!fval(u, UFL_TARGET)) return NULL; a = a_find(u->attribs, &at_target); assert(a || !"flag set, but no target found"); return (unit *) a->data.v; }
struct building *usiege(const unit * u) { attrib *a; if (!fval(u, UFL_SIEGE)) return NULL; a = a_find(u->attribs, &at_siege); assert(a || !"flag set, but no siege found"); return (struct building *)a->data.v; }
bool r_isforest(const region * r) { if (fval(r->terrain, FOREST_REGION)) { /* needs to be covered with at leas 48% trees */ int mincover = (int)(r->terrain->size * 0.48); int trees = rtrees(r, 2) + rtrees(r, 1); return (trees * TREESIZE >= mincover); } return false; }
group * get_group(const struct unit *u) { if (fval(u, UFL_GROUP)) { attrib * a = a_find(u->attribs, &at_group); if (a) { return (group *)a->data.v; } } return 0; }
bool can_survive(const unit * u, const region * r) { if ((fval(r->terrain, WALK_INTO) && (u_race(u)->flags & RCF_WALK)) || (fval(r->terrain, SWIM_INTO) && (u_race(u)->flags & RCF_SWIM)) || (fval(r->terrain, FLY_INTO) && (u_race(u)->flags & RCF_FLY))) { static const curse_type *ctype = NULL; if (has_horses(u) && !fval(r->terrain, WALK_INTO)) return false; if (!ctype) ctype = ct_find("holyground"); if (fval(u_race(u), RCF_UNDEAD) && curse_active(get_curse(r->attribs, ctype))) return false; return true; } return false; }