void CoreScript::UpdateScore(int n) { static const double FACTOR = 0.002; if (n) { // Tuned - somewhat sleazily - that basic 4 unit, 0 temple is one point. double score = CivTech() * double(n) * double(scoreTicker.Period()) * FACTOR; achievement.civTechScore += Min(1, int(score)); int team = ParentChit()->Team(); CDynArray<int> subTeams; if (Team::Instance()->IsController(team, &subTeams)) { for (int i = 0; i < subTeams.Size(); ++i) { CoreScript* subCore = CoreScript::GetCoreFromTeam(subTeams[i]); if (subCore) { score += 0.5 * subCore->CivTech() * double(n) * double(scoreTicker.Period()) * FACTOR; } } } // Push this to the GameItem, so it can be recorded in the history + census. GameItem* gi = ParentChit()->GetItem(); if (gi) { // Score is a 16 bit quantity... int s = achievement.civTechScore; if (s > 65535) s = 65535; gi->keyValues.Set(ISC::score, s); gi->UpdateHistory(); } } if (ParentChit()->GetItem()) { achievement.gold = Max(achievement.gold, ParentChit()->GetItem()->wallet.Gold()); achievement.population = Max(achievement.population, citizens.Size()); } }
void LumosGame::CopyFile(const char* src, const char* target) { GLString srcPath; GetSystemPath(GAME_APP_DIR, src, &srcPath); GLString targetPath; GetSystemPath(GAME_SAVE_DIR, target, &targetPath); FILE* fp = fopen(srcPath.c_str(), "rb"); GLASSERT(fp); if (fp) { FILE* tp = fopen(targetPath.c_str(), "wb"); GLASSERT(tp); if (tp) { CDynArray<U8> buf; fseek(fp, 0, SEEK_END); size_t size = ftell(fp); buf.PushArr(size); fseek(fp, 0, SEEK_SET); size_t didRead = fread(&buf[0], 1, size, fp); GLASSERT(didRead == 1); if (didRead == 1) { fwrite(buf.Mem(), 1, size, tp); } fclose(tp); } fclose(fp); } }
void TestThreadPool() { CDynArray<int> result; { // Empty: ThreadPool pool; pool.Wait(0); printf("Empty pool pass.\n"); } { int N = 8; ThreadPool pool; for (int i = 0; i < N; ++i) { pool.Add(TFunc, (void*)i); } pool.Wait(&result); result.Sort(); for (int i = 0; i < N; ++i) { GLASSERT(result[i] == i); } printf("Basic test pass.\n"); } { for (int pass = 0; pass < 2; ++pass) { int N = 100; ThreadPool pool; for (int i = 0; i < N; ++i) { pool.Add(TFunc, (void*)i); } pool.Wait(&result); result.Sort(); for (int i = 0; i < N; ++i) { GLASSERT(result[i] == i); } printf("Serial stress %d pass.\n", pass); } } { static const int P = 2; ThreadPool pool[P]; int N = 100; for (int i = 0; i < N; ++i) { for (int pass = 0; pass < P; ++pass) { pool[pass].Add(TFunc, (void*)i); } } for (int pass = 0; pass < P; ++pass) { pool[pass].Wait(&result); result.Sort(); for (int i = 0; i < N; ++i) { GLASSERT(result[i] == i); } } printf("Parallel stress pass.\n"); } }
void TestSpatialHash() { SpatialHash<int> spatial; CDynArray<int> query; Vector2I v = { 0, 0 }; spatial.Add(v, 0); spatial.Query(v, &query); GLASSERT(query.Size() == 1 && query[0] == 0); spatial.Remove(v, 0); GLASSERT(spatial.Query(v, &query) == 0); GLASSERT(spatial.Empty()); static int NUM = 2000; static int MULT = 7; static int MAP = 1024; for (int i = 0; i < NUM; ++i) { for (int j = 0; j < 4; ++j) { Vector2I pos = { (i*MULT) / MAP, (i*MULT) % MAP }; spatial.Add(pos, j); } } for (int i = 0; i < NUM; ++i) { Vector2I pos = { (i*MULT) / MAP, (i*MULT) % MAP }; spatial.Remove(pos, i%4); } for (int i = 0; i < NUM; ++i) { Vector2I pos = { (i*MULT) / MAP, (i*MULT) % MAP }; query.Clear(); spatial.Query(pos, &query); GLASSERT(query.Size() == 3); for (int j = 0; j < query.Size(); ++j) { GLASSERT(query[j] >= 0 && query[j] < 4 && query[j] != (i % 4)); } for (int j = 0; j < query.Size(); ++j) { spatial.Remove(pos, query[j]); } } GLASSERT(spatial.Empty()); printf("Spatial Hash test. nAllocated=%d nProbes=%d nSteps=%d eff=%.3f density=%.3f\n", spatial.NumAllocated(), spatial.NumProbes(), spatial.NumSteps(), spatial.Efficiency(), spatial.Density()); }
void MinSpanTree::Calc(const grinliz::Vector2I* points, int n) { nodes.Clear(); if (n < 1) return; Node start; start.pos = points[0]; start.parentPos = points[0]; nodes.Push(start); CDynArray<Vector2I> inSet; inSet.Reserve(n-1); for (int i = 1; i < n; ++i) { inSet.Push(points[i]); } while (!inSet.Empty()) { int bestNode = 0; int bestIn = 0; int bestScore = INT_MAX; for (int i = 0; i < nodes.Size(); ++i) { for (int k = 0; k < inSet.Size(); ++k) { int score = (inSet[k] - nodes[i].pos).LengthSquared(); if (score < bestScore) { bestScore = score; bestNode = i; bestIn = k; } } } GLASSERT(bestScore != INT_MAX); Vector2I vInSet = inSet[bestIn]; inSet.SwapRemove(bestIn); Node newNode; newNode.pos = vInSet; newNode.parentPos = nodes[bestNode].pos; newNode.nextSibling = nodes[bestNode].firstChild; nodes[bestNode].firstChild = nodes.Size(); nodes.Push(newNode); } RecWalkStr(0, 1.0f); }
CoreScript* CoreScript::CreateCore( const Vector2I& sector, int team, const ChitContext* context) { // Destroy the existing core. // Create a new core, attached to the player. CoreScript* cs = CoreScript::GetCore(sector); if (cs) { Chit* core = cs->ParentChit(); GLASSERT(core); CDynArray< Chit* > queryArr; // Tell all the AIs the core is going away. ChitHasAIComponent filter; Rectangle2F b = ToWorld2F(InnerSectorBounds(sector)); context->chitBag->QuerySpatialHash(&queryArr, b, 0, &filter); for (int i = 0; i < queryArr.Size(); ++i) { queryArr[i]->GetAIComponent()->ClearTaskList(); } //context.chitBag->QueueDelete(core); // QueueDelete is safer, but all kinds of asserts fire (correctly) // if 2 cores are in the same place. This may cause an issue // if CreateCore is called during the DoTick() // Setting the hp to 0 and then calling DoTick() // is a sleazy trick to clean up. core->GetItem()->hp = 0; if (core->GetHealthComponent()) { core->GetHealthComponent()->DoTick(1); } context->chitBag->DeleteChit(core); } const SectorData& sd = context->worldMap->GetSectorData(sector); if (sd.HasCore()) { int group = 0, id = 0; Team::SplitID(team, &group, &id); // Lots of trouble with this code. Used to assert, // but always seemed to be another case. White list // groups that *can* take over a core. if (team == TEAM_NEUTRAL || team == TEAM_TROLL || Team::IsDeity(team) || Team::IsDenizen(team)) { // Okay! take over. GLASSERT(!Team::IsDenizen(team) || id); // make sure rogues got filtered out. } else { team = group = id = 0; } Chit* chit = context->chitBag->NewBuilding(sd.core, "core", team); // 'in use' instead of blocking. MapSpatialComponent* ms = GET_SUB_COMPONENT(chit, SpatialComponent, MapSpatialComponent); GLASSERT(ms); ms->SetBlocks(false); CoreScript* cs = new CoreScript(); chit->Add(cs); GLASSERT(CoreScript::GetCore(ToSector(sd.core)) == cs); if (Team::IsDeity(team)) chit->GetItem()->SetProperName(Team::Instance()->TeamName(team)); else chit->GetItem()->SetProperName(sd.name); if (team != TEAM_NEUTRAL) { chit->GetItem()->SetSignificant(context->chitBag->GetNewsHistory(), ToWorld2F(chit->Position()), NewsEvent::DOMAIN_CREATED, NewsEvent::DOMAIN_DESTROYED, 0); // Make the dwellers defend the core. chit->Add(new GuardScript()); // Make all buildings to be this team. CDynArray<Chit*> buildings; Vector2I buildingSector = ToSector(chit->Position()); context->chitBag->FindBuilding(IString(), buildingSector, 0, LumosChitBag::EFindMode::NEAREST, &buildings, 0); for (int i = 0; i < buildings.Size(); ++i) { Chit* c = buildings[i]; if (c->GetItem() && c->GetItem()->IName() != ISC::core) { c->GetItem()->SetTeam(team); } } } return cs; } return 0; }