static void test_income(CuTest *tc) { race *rc; unit *u; test_setup(); rc = test_create_race("nerd"); u = test_create_unit(test_create_faction(rc), test_create_region(0, 0, 0)); CuAssertIntEquals(tc, 20, income(u)); u->number = 5; CuAssertIntEquals(tc, 100, income(u)); test_cleanup(); }
virtual void evaluate_income(int target_size, std::ostream &os) { if (not_available(target_size, os)) { return; } int remaining = target_size; price_t income(0); // start from the end of the order list to maximize profit // iterate over sorted orders; O(N), N/2 on average sorted_orders_t::iterator it = m_sorted_orders.begin(); for (; it != m_sorted_orders.end() && remaining > 0; ++it) { order_ptr & ord = (*it); if (!ord->active()) { continue; } int shares = std::min(remaining, ord->size()); income += ord->price_of(shares); remaining -= shares; } report_income(income, os); }
// Lambert 面の Radiance の評価 Color PathTracer::Radiance_Lambert(const Scene &scene, const Ray &ray, Random &rnd, const int depth, Scene::IntersectionInformation &intersect, const Vector3 &normal, double russian_roulette_prob) { Color direct; // 直接光を評価する if (m_performNextEventEstimation && intersect.object->material.emission.lengthSq() == 0) { direct = DirectRadiance_Lambert(scene, ray, rnd, depth, true, intersect, normal); } Vector3 w,u,v; w = normal; if (fabs(normal.x) > EPS) { u = Vector3(0,1,0).cross(w); } else { u = Vector3(1,0,0).cross(w); } v = w.cross(u); double u1 = rnd.nextDouble(); double u2 = rnd.nextDouble(); // pdf is 1/PI //double r1 = PI*u1; // Φ //double r2 = 1-u2; // cosθ //double r3 = sqrt(1-r2*r2); // sinθ //double pdf = 1/PI; // pdf is cosθ/PI double r1 = 2*PI*u1; double r2 = sqrt(u2); // cosθ double r3 = sqrt(1-u2); // sinθ double pdf = r2/PI; //const double r1 = 2 * PI * rnd.nextDouble(); //const double r2 = rnd.nextDouble(), r2s = sqrt(r2); //Vector3 dir = u * cos(r1) * r2s + v * sin(r1) * r2s + w * sqrt(1.0-r2); //dir.normalize(); //weight = intersect.object->color / russian_roulette_probability; Vector3 dir = u*r3*cos(r1) + v*r3*sin(r1) + w*r2; dir.normalize(); //Color weight = intersect.object->color / PI * r2 / pdf / russian_roulette_prob; Color weight = intersect.texturedHitpointColor; Color income(0,0,0); if (intersect.object->material.emission.lengthSq() == 0) { income = Radiance(scene, Ray(intersect.hit.position, dir), rnd, depth + 1); } // direct はすでに反射率が乗算済みなので、weightを掛ける必要はない return ( Vector3(weight.x*income.x, weight.y*income.y, weight.z*income.z) + direct ) / russian_roulette_prob; }
void BudgetWindow::GenerateBudget(const bool &zero) { // Generate a budget based on the last year's transactions ReportGrid income(1,0), spending(1,0); gDatabase.DBCommand("delete from budgetlist", "BudgetWindow::GenerateBudget:empty budget"); CppSQLite3Query query; query = gDatabase.DBQuery("select * from categorylist order by name", "BudgetWindow::GenerateBudget:get categories"); if(query.eof()) return; float maxwidth=fCategoryList->StringWidth(TRANSLATE("Category")); while(!query.eof()) { BString catname = DeescapeIllegalCharacters(query.getStringField(0)); if(catname.ICompare(TRANSLATE("Transfer"))==0) { query.nextRow(); continue; } bool isexpense = !query.getIntField(1); if(isexpense) { spending.AddItem(); spending.SetRowTitle(spending.CountItems()-1,catname.String()); } else { income.AddItem(); income.SetRowTitle(income.CountItems()-1,catname.String()); } float tempwidth = fCategoryList->StringWidth(catname.String()); maxwidth = MAX(maxwidth,tempwidth); query.nextRow(); } query.finalize(); // Now that we have the list of categories, query for transactions for each // account from each category BString querystring; Fixed cattotal; for(int32 i=0; i<income.CountItems(); i++) { querystring = ""; cattotal = 0; if(!zero) { for(int32 j=0; j<gDatabase.CountAccounts(); j++) { Account *acc = gDatabase.AccountAt(j); querystring = "select sum(amount) from account_" ; querystring << acc->GetID() << " where category = '" << EscapeIllegalCharacters(income.RowTitle(i)) << "' and date > " << DecrementDateByYear(GetCurrentDate()) << ";"; query = gDatabase.DBQuery(querystring.String(), "BudgetWindow::GenerateBudget:get category"); cattotal.AddPremultiplied(query.getInt64Field(0)); query.finalize(); } cattotal /= 12; cattotal.Round(); } income.SetValue(0,i,cattotal); gDatabase.AddBudgetEntry(BudgetEntry(income.RowTitle(i),cattotal,BUDGET_MONTHLY,false)); } for(int32 i=0; i<spending.CountItems(); i++) { querystring = ""; cattotal = 0; if(!zero) { for(int32 j=0; j<gDatabase.CountAccounts(); j++) { Account *acc = gDatabase.AccountAt(j); querystring = "select sum(amount) from account_" ; querystring << acc->GetID() << " where category = '" << EscapeIllegalCharacters(spending.RowTitle(i)) << "';"; query = gDatabase.DBQuery(querystring.String(), "BudgetWindow::GenerateBudget:get category"); cattotal.AddPremultiplied(query.getInt64Field(0)); query.finalize(); } cattotal /= 12; cattotal.Round(); } spending.SetValue(0,i,cattotal); gDatabase.AddBudgetEntry(BudgetEntry(spending.RowTitle(i),cattotal,BUDGET_MONTHLY,true)); } }
void new_turn() { gold_ += income(); }
vec3 DirectLightIntegrator::income(const Ray &r, const shared_ptr<Scene> &scene, int level) { vec3 L(0.0f); Intersection hit(NULL, NULL, CONST_FAR); // Is there intersection? if (!scene->intersect(r, hit)) { return L; } // Is this intersection on the light? if (hit.type == INTERSECTION_LIGHT) { // Simply return the color from the light. const Light *light = static_cast<const Light *>(hit.intersectable); return light->Le(hit.point) * clamp(dot(hit.normal, -r.d), 0.0f, 1.0f); } // Sample for one light. if (!hit.m->bsdf->isDelta()) { // This is not a delta brdf. Randomly pick one light. int lightId = floor(Sampler::sample1D(0.0f, (float)scene->lights.size() - 0.1f)); const shared_ptr<Light> &light = scene->lights[lightId]; // Get the shadow ray and the distance to the light. vec3 Lo(0.0f); for (int i = 0; i < nLightSamples; ++i) { auto sample = light->genShadowRay(hit); Ray shadowRay = sample.first; float lightPDF = sample.second; if (lightPDF < CONST_EPSILON) { continue; } // Use the shadow ray to find intersect. if (scene->occlude(shadowRay)) { continue; } // Get the light color. vec3 pointOnLight = shadowRay.o + shadowRay.tmax * shadowRay.d; vec3 Le = light->Le(pointOnLight); vec3 f = hit.m->bsdf->bsdf(hit, r.d, shadowRay.d); float w = powerHeuristec(lightPDF, nLightSamples, hit.m->bsdf->pdf(hit, r.d, shadowRay.d), nBSDFSamples); // Here the geometry term is inside the pdf. // Use power heuristic. Lo += f * Le * w / lightPDF; } Lo /= nLightSamples; L += Lo; // Sample for BSDF. if (level < maxDepth - 1) { vec3 LBSDF(0.0f); for (int i = 0; i < nBSDFSamples; ++i) { while (true) { auto sample = hit.m->bsdf->sample(hit, r.d); if (sample.second > 0.1f) { auto Li = income(sample.first, scene, level + 1); vec3 f = hit.m->bsdf->bsdf(hit, r.d, sample.first.d); float w = powerHeuristec(sample.second, nBSDFSamples, light->pdfRay(hit, sample.first.d), nLightSamples); //float w = 1.0f; LBSDF += w * f * Li / sample.second; break; } } } LBSDF /= nBSDFSamples; L += clamp(LBSDF, 0.0f, 1.0f); } } else { // This is a delta brdf. Just sample the delta direction. if (level < maxDepth - 1) { auto sample = hit.m->bsdf->sample(hit, r.d); auto Li = income(sample.first, scene, level + 1); vec3 f = hit.m->bsdf->bsdf(hit, r.d, sample.first.d); L += f * Li; } } return L; }
static order *plan_dragon(unit * u) { attrib *ta = a_find(u->attribs, &at_targetregion); region *r = u->region; region *tr = NULL; bool move = false; order *long_order = NULL; if (ta == NULL) { move |= (r->land == 0 || r->land->peasants == 0); /* when no peasants, move */ move |= (r->land == 0 || r->land->money == 0); /* when no money, move */ } move |= chance(0.04); /* 4% chance to change your mind */ if (u_race(u) == get_race(RC_WYRM) && !move) { unit *u2; for (u2 = r->units; u2; u2 = u2->next) { /* wyrme sind einzelgänger */ if (u2 == u) { /* we do not make room for newcomers, so we don't need to look at them */ break; } if (u2 != u && u_race(u2) == u_race(u) && chance(0.5)) { move = true; break; } } } if (move) { /* dragon gets bored and looks for a different place to go */ ta = set_new_dragon_target(u, u->region, DRAGON_RANGE); } else ta = a_find(u->attribs, &at_targetregion); if (ta != NULL) { tr = (region *)ta->data.v; if (tr == NULL || !path_exists(u->region, tr, DRAGON_RANGE, allowed_dragon)) { ta = set_new_dragon_target(u, u->region, DRAGON_RANGE); if (ta) tr = findregion(ta->data.sa[0], ta->data.sa[1]); } } if (tr != NULL) { assert(long_order == NULL); switch (old_race(u_race(u))) { case RC_FIREDRAGON: long_order = make_movement_order(u, tr, 4, allowed_dragon); break; case RC_DRAGON: long_order = make_movement_order(u, tr, 3, allowed_dragon); break; case RC_WYRM: long_order = make_movement_order(u, tr, 1, allowed_dragon); break; default: break; } if (long_order) { reduce_weight(u); } if (rng_int() % 100 < 15) { const struct locale *lang = u->faction->locale; /* do a growl */ if (rname(tr, lang)) { addlist(&u->orders, create_order(K_MAIL, lang, "%s '%s... %s %s %s'", LOC(lang, parameters[P_REGION]), random_growl(), u->number == 1 ? "Ich rieche" : "Wir riechen", "etwas in", rname(tr, u->faction->locale))); } } } else { /* we have no target. do we like it here, then? */ long_order = get_money_for_dragon(u->region, u, income(u)); if (long_order == NULL) { /* money is gone, need a new target */ set_new_dragon_target(u, u->region, DRAGON_RANGE); } else if (u_race(u) != get_race(RC_FIREDRAGON)) { /* neue dracoiden! */ if (r->land && !fval(r->terrain, FORBIDDEN_REGION)) { int ra = 20 + rng_int() % 100; if (get_money(u) > ra * 50 + 100 && rng_int() % 100 < 50) { recruit_dracoids(u, ra); } } } } if (long_order == NULL) { skill_t sk = SK_PERCEPTION; /* study perception (or a random useful skill) */ while (!skill_enabled(sk) || u_race(u)->bonus[sk] < -5) { sk = (skill_t)(rng_int() % MAXSKILLS); } long_order = create_order(K_STUDY, u->faction->locale, "'%s'", skillname(sk, u->faction->locale)); } return long_order; }