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; } } } }
int Intervals::in(int x) { if (!n) return 0; if (i_find(this, x) > 0) return 1; return 0; }
/* * This routine is called when the 'Delete' menu item is selected */ void fun_del(WORD sobj) { ANODE *pa; WNODE *pw; WORD disk_found = 0; /* * if the item selected is on the desktop, there may be other desktop * items that have been selected; make sure we process all of them */ if ( (pa = i_find(0, sobj, NULL, NULL)) ) { if (wants_to_delete_files() == FALSE) /* i.e. remove icons or cancel */ return; for ( ; sobj; sobj = win_isel(G.g_screen, DROOT, sobj)) { pa = i_find(0,sobj,NULL,NULL); if (!pa) continue; if (pa->a_type == AT_ISDISK) { disk_found++; if (delete_disk(pa)) do_refresh_drive(pa->a_letter); } } if (disk_found) { desk_clear(0); return; } } /* * otherwise, process path associated with selected window icon, if any */ pw = win_find(G.g_cwin); if (pw) { if (fun_op(OP_DELETE, -1, pw->w_path, NULL)) fun_rebld(pw); } }
/* * Routine to call when several icons have been dragged from a * window to another window (it might be the same window) and * dropped on a particular icon or open space. * * Note that, for DESK1, this is NEVER called if either the source * or destination is the desktop. Therefore 'datype' can ONLY be * AT_ISFILE or AT_ISFOLD. */ void fun_drag(WORD src_wh, WORD dst_wh, WORD dst_ob, WORD dulx, WORD duly, WORD keystate) { WORD ret, datype, op; WNODE *psw, *pdw; ANODE *pda; FNODE *pdf; BYTE destpath[MAXPATHLEN]; op = (keystate&MODE_CTRL) ? OP_MOVE : OP_COPY; psw = win_find(src_wh); if (!psw) return; pdw = win_find(dst_wh); if (!pdw) return; pda = i_find(dst_wh, dst_ob, &pdf, NULL); datype = (pda) ? pda->a_type : AT_ISFILE; /* set up default destination path name */ strcpy(destpath, pdw->w_path->p_spec); /* if destination is folder, insert folder name in path */ if (datype == AT_ISFOLD) add_path(destpath, pdf->f_name); ret = fun_op(op, -1, psw->w_path, destpath); if (ret) { if (src_wh != dst_wh) desk_clear(src_wh); if (op == OP_MOVE) fun_rebld(psw); fun_rebld(pdw); /* * if we copied into a folder, we must check to see if it's * open in a window and, if so, redraw it too */ if (datype == AT_ISFOLD) { pdw = fold_wind(destpath); if (pdw) fun_rebld(pdw); } } }
// insert into interval with merge void Intervals::insert(int x) { if (!n) { add(x); add(x); return; } int l = i_find(this, x); if (l > 0) return; l = -l - 1; if (x > v[l + 1]) { if (x == v[l + 1] + 1) { v[l + 1]++; goto Lmerge; } l += 2; if (l < n) { if (x == v[l] - 1) { v[l]--; goto Lmerge; } } goto Lmore; } else { INT_ASSERT(x < v[l]); if (x == v[l] - 1) { v[l]--; goto Lmerge; } if (!l) goto Lmore; l -= 2; if (x == v[l + 1] + 1) { v[l + 1]++; goto Lmerge; } } Lmore: fill(n + 2); if (n - 2 - l > 0) memmove(v + l + 2, v + l, sizeof(int) * (n - 2 - l)); v[l] = x; v[l+1] = x; return; Lmerge: if (l) { if (v[l] - v[l-1] < 2) { l -= 2; goto Ldomerge; } } if (l < n - 2) { if (v[l + 2] - v[l + 1] < 2) goto Ldomerge; } return; Ldomerge: memmove(v + l + 1, v + l + 3, sizeof(int) * (n - 3 - l)); n -= 2; goto Lmerge; }
/* Rosthauch */ int sp_combatrosthauch(struct castorder * co) { fighter * fi = co->magician.fig; int level = co->level; double power = co->force; battle *b = fi->side->battle; selist *ql, *fgs; int force = lovar(power * 15); int qi, k = 0; if (!count_enemies(b, fi, FIGHT_ROW, BEHIND_ROW - 1, SELECT_ADVANCE | SELECT_FIND)) { message *msg = msg_message("rust_effect_0", "mage", fi->unit); message_all(b, msg); msg_release(msg); return 0; } fgs = select_fighters(b, fi->side, FS_ENEMY, select_armed, NULL); scramble_fighters(fgs); for (qi = 0, ql = fgs; force>0 && ql; selist_advance(&ql, &qi, 1)) { fighter *df = (fighter *)selist_get(ql, qi); int w; for (w = 0; df->weapons[w].type != NULL; ++w) { weapon *wp = df->weapons; if (df->unit->items && force > 0) { item ** itp = i_find(&df->unit->items, wp->type->itype); if (*itp) { item *it = *itp; requirement *mat = wp->type->itype->construction->materials; int n = force; if (it->number < n) n = it->number; while (mat && mat->number > 0) { if (mat->rtype == get_resourcetype(R_IRON)) { int p; force -= n; k += n; i_change(itp, wp->type->itype, -n); for (p = 0; n && p != df->unit->number; ++p) { if (df->person[p].melee == wp) { df->person[p].melee = NULL; --n; } } for (p = 0; n && p != df->unit->number; ++p) { if (df->person[p].missile == wp) { df->person[p].missile = NULL; --n; } } break; } mat++; } } } } } selist_free(fgs); if (k == 0) { /* keine Waffen mehr da, die zerstoert werden koennten */ message *msg = msg_message("rust_effect_1", "mage", fi->unit); message_all(b, msg); msg_release(msg); fi->magic = 0; /* kaempft nichtmagisch weiter */ level = 0; } else { message *msg = msg_message("rust_effect_2", "mage", fi->unit); message_all(b, msg); msg_release(msg); } return level; }
/* * Based on current selected icons, figure out which menu items * should be selected (deselected) */ static void men_update(OBJECT *tree) { WORD item, nsel, isapp; const BYTE *pvalue; ANODE *appl; pvalue = 0; /* enable all items */ for (item = OPENITEM; item <= PREFITEM; item++) menu_ienable(tree, item, 1); can_iapp = TRUE; can_show = TRUE; can_del = TRUE; /* disable some items */ men_list(tree, ILL_ITEM, FALSE); nsel = 0; for (item = 0; (item=win_isel(G.g_screen, G.g_croot, item)) != 0; nsel++) { appl = i_find(G.g_cwin, item, NULL, &isapp); if (!appl) continue; switch(appl->a_type) { case AT_ISFILE: if (isapp || is_installed(appl)) pvalue = ILL_FILE; else { pvalue = ILL_DOCU; can_iapp = FALSE; } break; case AT_ISFOLD: pvalue = ILL_FOLD; can_iapp = FALSE; break; case AT_ISDISK: pvalue = (appl->a_aicon == IG_FLOPPY) ? ILL_FDSK : ILL_HDSK; can_iapp = FALSE; break; case AT_ISTRSH: /* Trash */ pvalue = ILL_TRASH; can_del = FALSE; break; } men_list(tree, pvalue, FALSE); /* disable certain items */ } if (win_ontop()) pvalue = ILL_DESKTOP; else pvalue = ILL_NOTOP; if (pvalue == ILL_DESKTOP) men_list(tree, pvalue, TRUE); else men_list(tree, pvalue, FALSE); if (nsel != 1) { if (nsel) { pvalue = ILL_YSEL; can_show = FALSE; } else { pvalue = ILL_NOSEL; can_show = FALSE; can_del = FALSE; can_iapp = FALSE; } men_list(tree, pvalue, FALSE); } #if CONF_WITH_SHUTDOWN menu_ienable(tree, QUITITEM, can_shutdown()); #else menu_ienable(tree, QUITITEM, 0); #endif #if WITH_CLI == 0 menu_ienable(tree, CLIITEM, 0); #endif }
/** Use up resources for building an object. * Build up to 'size' points of 'type', where 'completed' * of the first object have already been finished. return the * actual size that could be built. */ int build(unit * u, const construction * ctype, int completed, int want) { const construction *type = ctype; int skills = INT_MAX; /* number of skill points remainig */ int basesk = 0; int made = 0; if (want <= 0) return 0; if (type == NULL) return ENOMATERIALS; if (type->improvement == NULL && completed == type->maxsize) return ECOMPLETE; if (type->btype != NULL) { building *b; if (!u->building || u->building->type != type->btype) { return EBUILDINGREQ; } b = inside_building(u); if (b == NULL) return EBUILDINGREQ; } if (type->skill != NOSKILL) { int effsk; int dm = get_effect(u, oldpotiontype[P_DOMORE]); assert(u->number); basesk = effskill(u, type->skill); if (basesk == 0) return ENEEDSKILL; effsk = basesk; if (inside_building(u)) { effsk = skillmod(u->building->type->attribs, u, u->region, type->skill, effsk, SMF_PRODUCTION); } effsk = skillmod(type->attribs, u, u->region, type->skill, effsk, SMF_PRODUCTION); if (effsk < 0) return effsk; /* pass errors to caller */ if (effsk == 0) return ENEEDSKILL; skills = effsk * u->number; /* technically, nimblefinge and domore should be in a global set of * "game"-attributes, (as at_skillmod) but for a while, we're leaving * them in here. */ if (dm != 0) { /* Auswirkung Schaffenstrunk */ dm = _min(dm, u->number); change_effect(u, oldpotiontype[P_DOMORE], -dm); skills += dm * effsk; } } for (; want > 0 && skills > 0;) { int c, n; /* skip over everything that's already been done: * type->improvement==NULL means no more improvements, but no size limits * type->improvement==type means build another object of the same time * while material lasts type->improvement==x means build x when type * is finished */ while (type->improvement != NULL && type->improvement != type && type->maxsize > 0 && type->maxsize <= completed) { completed -= type->maxsize; type = type->improvement; } if (type == NULL) { if (made == 0) return ECOMPLETE; break; /* completed */ } /* Hier ist entweder maxsize == -1, oder completed < maxsize. * Andernfalls ist das Datenfile oder sonstwas kaputt... * (enno): Nein, das ist für Dinge, bei denen die nächste Ausbaustufe * die gleiche wie die vorherige ist. z.b. gegenstände. */ if (type->maxsize > 1) { completed = completed % type->maxsize; } else { completed = 0; assert(type->reqsize >= 1); } if (basesk < type->minskill) { if (made == 0) return ELOWSKILL; /* not good enough to go on */ } /* n = maximum buildable size */ if (type->minskill > 1) { n = skills / type->minskill; } else { n = skills; } /* Flinkfingerring wirkt nicht auf Mengenbegrenzte (magische) * Talente */ if (skill_limit(u->faction, type->skill) == INT_MAX) { const resource_type *ring = get_resourcetype(R_RING_OF_NIMBLEFINGER); item *itm = ring ? *i_find(&u->items, ring->itype) : 0; int i = itm ? itm->number : 0; if (i > 0) { int rings = _min(u->number, i); n = n * ((roqf_factor() - 1) * rings + u->number) / u->number; } } if (want < n) n = want; if (type->maxsize > 0) { n = _min(type->maxsize - completed, n); if (type->improvement == NULL) { want = n; } } if (type->materials) for (c = 0; n > 0 && type->materials[c].number; c++) { const struct resource_type *rtype = type->materials[c].rtype; int need, prebuilt; int canuse = get_pooled(u, rtype, GET_DEFAULT, INT_MAX); if (inside_building(u)) { canuse = matmod(u->building->type->attribs, u, rtype, canuse); } if (canuse < 0) return canuse; /* pass errors to caller */ canuse = matmod(type->attribs, u, rtype, canuse); if (type->reqsize > 1) { prebuilt = required(completed, type->reqsize, type->materials[c].number); for (; n;) { need = required(completed + n, type->reqsize, type->materials[c].number); if (need - prebuilt <= canuse) break; --n; /* TODO: optimieren? */ } } else { int maxn = canuse / type->materials[c].number; if (maxn < n) n = maxn; } } if (n <= 0) { if (made == 0) return ENOMATERIALS; else break; } if (type->materials) for (c = 0; type->materials[c].number; c++) { const struct resource_type *rtype = type->materials[c].rtype; int prebuilt = required(completed, type->reqsize, type->materials[c].number); int need = required(completed + n, type->reqsize, type->materials[c].number); int multi = 1; int canuse = 100; /* normalization */ if (inside_building(u)) canuse = matmod(u->building->type->attribs, u, rtype, canuse); if (canuse < 0) return canuse; /* pass errors to caller */ canuse = matmod(type->attribs, u, rtype, canuse); assert(canuse % 100 == 0 || !"only constant multipliers are implemented in build()"); multi = canuse / 100; if (canuse < 0) return canuse; /* pass errors to caller */ use_pooled(u, rtype, GET_DEFAULT, (need - prebuilt + multi - 1) / multi); } made += n; skills -= n * type->minskill; want -= n; completed = completed + n; } /* Nur soviel PRODUCEEXP wie auch tatsaechlich gemacht wurde */ produceexp(u, ctype->skill, _min(made, u->number)); return made; }
void build_road(region * r, unit * u, int size, direction_t d) { int n, left; region *rn = rconnect(r, d); assert(u->number); if (!eff_skill(u, SK_ROAD_BUILDING, r)) { cmistake(u, u->thisorder, 103, MSG_PRODUCE); return; } if (besieged(u)) { cmistake(u, u->thisorder, 60, MSG_PRODUCE); return; } if (rn == NULL || rn->terrain->max_road < 0) { cmistake(u, u->thisorder, 94, MSG_PRODUCE); return; } if (r->terrain->max_road < 0) { cmistake(u, u->thisorder, 94, MSG_PRODUCE); return; } if (r->terrain == newterrain(T_SWAMP)) { /* wenn kein Damm existiert */ const struct building_type *bt_dam = bt_find("dam"); if (!bt_dam || !buildingtype_exists(r, bt_dam, true)) { cmistake(u, u->thisorder, 132, MSG_PRODUCE); return; } } else if (r->terrain == newterrain(T_DESERT)) { const struct building_type *bt_caravan = bt_find("caravan"); /* wenn keine Karawanserei existiert */ if (!bt_caravan || !buildingtype_exists(r, bt_caravan, true)) { cmistake(u, u->thisorder, 133, MSG_PRODUCE); return; } } else if (r->terrain == newterrain(T_GLACIER)) { const struct building_type *bt_tunnel = bt_find("tunnel"); /* wenn kein Tunnel existiert */ if (!bt_tunnel || !buildingtype_exists(r, bt_tunnel, true)) { cmistake(u, u->thisorder, 131, MSG_PRODUCE); return; } } /* left kann man noch bauen */ left = r->terrain->max_road - rroad(r, d); /* hoffentlich ist r->road <= r->terrain->max_road, n also >= 0 */ if (left <= 0) { ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, "error_roads_finished", "")); return; } if (size > 0) left = _min(size, left); /* baumaximum anhand der rohstoffe */ if (u_race(u) == get_race(RC_STONEGOLEM)) { n = u->number * GOLEM_STONE; } else { n = get_pooled(u, get_resourcetype(R_STONE), GET_DEFAULT, left); if (n == 0) { cmistake(u, u->thisorder, 151, MSG_PRODUCE); return; } } left = _min(n, left); /* n = maximum by skill. try to maximize it */ n = u->number * eff_skill(u, SK_ROAD_BUILDING, r); if (n < left) { const resource_type *ring = get_resourcetype(R_RING_OF_NIMBLEFINGER); item *itm = ring ? *i_find(&u->items, ring->itype) : 0; if (itm != NULL && itm->number > 0) { int rings = _min(u->number, itm->number); n = n * ((roqf_factor() - 1) * rings + u->number) / u->number; } } if (n < left) { int dm = get_effect(u, oldpotiontype[P_DOMORE]); if (dm != 0) { int sk = eff_skill(u, SK_ROAD_BUILDING, r); int todo = (left - n + sk - 1) / sk; todo = _min(todo, u->number); dm = _min(dm, todo); change_effect(u, oldpotiontype[P_DOMORE], -dm); n += dm * sk; } /* Auswirkung Schaffenstrunk */ } /* make minimum of possible and available: */ n = _min(left, n); /* n is now modified by several special effects, so we have to * minimize it again to make sure the road will not grow beyond * maximum. */ rsetroad(r, d, rroad(r, d) + (short)n); if (u_race(u) == get_race(RC_STONEGOLEM)) { int golemsused = n / GOLEM_STONE; if (n % GOLEM_STONE != 0) { ++golemsused; } scale_number(u, u->number - golemsused); } else { use_pooled(u, get_resourcetype(R_STONE), GET_DEFAULT, n); /* Nur soviel PRODUCEEXP wie auch tatsaechlich gemacht wurde */ produceexp(u, SK_ROAD_BUILDING, _min(n, u->number)); } ADDMSG(&u->faction->msgs, msg_message("buildroad", "region unit size", r, u, n)); }