//key of last start rect in the map unsigned int IBattle::GetLastRectIdx() const { if(GetNumRects() > 0) return m_rects.rbegin()->first; return 0; }
//return the lowest currently unused key in the map of rects. unsigned int IBattle::GetNextFreeRectIdx() const { //check for unused allyno keys for(unsigned int i = 0; i <= GetLastRectIdx(); i++) { if(!GetStartRect(i).IsOk()) return i; } return GetNumRects(); //if all rects are in use, or no elements exist, return first possible available allyno. }
void nsRegion::SimplifyInward (uint32_t aMaxRects) { NS_ASSERTION(aMaxRects >= 1, "Invalid max rect count"); if (GetNumRects() <= aMaxRects) return; SetEmpty(); }
void nsRegion::SimplifyOutward (uint32_t aMaxRects) { MOZ_ASSERT(aMaxRects >= 1, "Invalid max rect count"); if (GetNumRects() <= aMaxRects) return; pixman_box32_t *boxes; int n; boxes = pixman_region32_rectangles(&mImpl, &n); // Try combining rects in horizontal bands into a single rect int dest = 0; for (int src = 1; src < n; src++) { // The goal here is to try to keep groups of rectangles that are vertically // discontiguous as separate rectangles in the final region. This is // simple and fast to implement and page contents tend to vary more // vertically than horizontally (which is why our rectangles are stored // sorted by y-coordinate, too). // // Note: if boxes share y1 because of the canonical representation they // will share y2 while ((src < (n)) && boxes[dest].y1 == boxes[src].y1) { // merge box[i] and box[i+1] boxes[dest].x2 = boxes[src].x2; src++; } if (src < n) { dest++; boxes[dest] = boxes[src]; } } uint32_t reducedCount = dest+1; // pixman has a special representation for // regions of 1 rectangle. So just use the // bounds in that case if (reducedCount > 1 && reducedCount <= aMaxRects) { // reach into pixman and lower the number // of rects stored in data. mImpl.data->numRects = reducedCount; } else { *this = GetBounds(); } }
nsRect nsRegion::GetLargestRectangle (const nsRect& aContainingRect) const { nsRect bestRect; if (GetNumRects() <= 1) { bestRect = GetBounds(); return bestRect; } AxisPartition xaxis, yaxis; // Step 1: Calculate the grid lines nsRegionRectIterator iter(*this); const nsRect *currentRect; while ((currentRect = iter.Next())) { xaxis.InsertCoord(currentRect->x); xaxis.InsertCoord(currentRect->XMost()); yaxis.InsertCoord(currentRect->y); yaxis.InsertCoord(currentRect->YMost()); } if (!aContainingRect.IsEmpty()) { xaxis.InsertCoord(aContainingRect.x); xaxis.InsertCoord(aContainingRect.XMost()); yaxis.InsertCoord(aContainingRect.y); yaxis.InsertCoord(aContainingRect.YMost()); } // Step 2: Fill out the grid with the areas // Note: due to the ordering of rectangles in the region, it is not always // possible to combine steps 2 and 3 so we don't try to be clever. int32_t matrixHeight = yaxis.GetNumStops() - 1; int32_t matrixWidth = xaxis.GetNumStops() - 1; int32_t matrixSize = matrixHeight * matrixWidth; nsTArray<SizePair> areas(matrixSize); areas.SetLength(matrixSize); iter.Reset(); while ((currentRect = iter.Next())) { int32_t xstart = xaxis.IndexOf(currentRect->x); int32_t xend = xaxis.IndexOf(currentRect->XMost()); int32_t y = yaxis.IndexOf(currentRect->y); int32_t yend = yaxis.IndexOf(currentRect->YMost()); for (; y < yend; y++) { nscoord height = yaxis.StopSize(y); for (int32_t x = xstart; x < xend; x++) { nscoord width = xaxis.StopSize(x); int64_t size = width*int64_t(height); if (currentRect->Intersects(aContainingRect)) { areas[y*matrixWidth+x].mSizeContainingRect = size; } areas[y*matrixWidth+x].mSize = size; } } } // Step 3: Find the maximum submatrix sum that does not contain a rectangle { // First get the prefix sum array int32_t m = matrixHeight + 1; int32_t n = matrixWidth + 1; nsTArray<SizePair> pareas(m*n); pareas.SetLength(m*n); for (int32_t y = 1; y < m; y++) { for (int32_t x = 1; x < n; x++) { SizePair area = areas[(y-1)*matrixWidth+x-1]; if (!area.mSize) { area = SizePair::VeryLargeNegative(); } area = area + pareas[ y*n+x-1] + pareas[(y-1)*n+x ] - pareas[(y-1)*n+x-1]; pareas[y*n+x] = area; } } // No longer need the grid areas.SetLength(0); SizePair bestArea; struct { int32_t left, top, right, bottom; } bestRectIndices = { 0, 0, 0, 0 }; for (int32_t m1 = 0; m1 < m; m1++) { for (int32_t m2 = m1+1; m2 < m; m2++) { nsTArray<SizePair> B; B.SetLength(n); for (int32_t i = 0; i < n; i++) { B[i] = pareas[m2*n+i] - pareas[m1*n+i]; } int32_t minIdx, maxIdx; SizePair area = MaxSum1D(B, n, &minIdx, &maxIdx); if (area > bestArea) { bestRectIndices.left = minIdx; bestRectIndices.top = m1; bestRectIndices.right = maxIdx; bestRectIndices.bottom = m2; bestArea = area; } } } bestRect.MoveTo(xaxis.StopAt(bestRectIndices.left), yaxis.StopAt(bestRectIndices.top)); bestRect.SizeTo(xaxis.StopAt(bestRectIndices.right) - bestRect.x, yaxis.StopAt(bestRectIndices.bottom) - bestRect.y); } return bestRect; }
void Battle::Autobalance( BalanceType balance_type, bool support_clans, bool strong_clans, int numallyteams ) { wxLogMessage(_T("Autobalancing alliances, type=%d, clans=%d, strong_clans=%d, numallyteams=%d"),balance_type, support_clans,strong_clans, numallyteams); //size_t i; //int num_alliances; std::vector<Alliance>alliances; if ( numallyteams == 0 || numallyteams == -1 ) // 0 or 1 -> use num start rects { int ally = 0; for ( unsigned int i = 0; i < GetNumRects(); ++i ) { BattleStartRect sr = GetStartRect(i); if ( sr.IsOk() ) { ally=i; alliances.push_back( Alliance( ally ) ); ally++; } } // make at least two alliances while ( alliances.size() < 2 ) { alliances.push_back( Alliance( ally ) ); ally++; } } else { for ( int i = 0; i < numallyteams; i++ ) alliances.push_back( Alliance( i ) ); } //for(i=0;i<alliances.size();++i)alliances[i].allynum=i; wxLogMessage( _T("number of alliances: %u"), alliances.size() ); std::vector<User*> players_sorted; players_sorted.reserve( GetNumUsers() ); for ( size_t i = 0; i < GetNumUsers(); ++i ) { User& usr = GetUser( i ); if ( !usr.BattleStatus().spectator ) { players_sorted.push_back( &usr ); } } // remove players in the same team so only one remains std::map< int, User*> dedupe_teams; for ( std::vector<User*>::iterator it = players_sorted.begin(); it != players_sorted.end(); it++ ) { dedupe_teams[(*it)->BattleStatus().team] = *it; } players_sorted.clear(); players_sorted.reserve( dedupe_teams.size() ); for ( std::map<int, User*>::iterator it = dedupe_teams.begin(); it != dedupe_teams.end(); it++ ) { players_sorted.push_back( it->second ); } shuffle( players_sorted ); std::map<wxString, Alliance> clan_alliances; if ( support_clans ) { for ( size_t i=0; i < players_sorted.size(); ++i ) { wxString clan = players_sorted[i]->GetClan(); if ( !clan.empty() ) { clan_alliances[clan].AddPlayer( players_sorted[i] ); } } }; if ( balance_type != balance_random ) std::sort( players_sorted.begin(), players_sorted.end(), PlayerRankCompareFunction ); if ( support_clans ) { std::map<wxString, Alliance>::iterator clan_it = clan_alliances.begin(); while ( clan_it != clan_alliances.end() ) { Alliance &clan = (*clan_it).second; // if clan is too small (only 1 clan member in battle) or too big, dont count it as clan if ( ( clan.players.size() < 2 ) || ( !strong_clans && ( clan.players.size() > ( ( players_sorted.size() + alliances.size() -1 ) / alliances.size() ) ) ) ) { wxLogMessage( _T("removing clan %s"), (*clan_it).first.c_str() ); std::map<wxString, Alliance>::iterator next = clan_it; ++next; clan_alliances.erase( clan_it ); clan_it = next; continue; } wxLogMessage( _T("Inserting clan %s"), (*clan_it).first.c_str() ); std::sort( alliances.begin(), alliances.end() ); float lowestrank = alliances[0].ranksum; int rnd_k = 1;// number of alliances with rank equal to lowestrank while ( size_t( rnd_k ) < alliances.size() ) { if ( fabs( alliances[rnd_k].ranksum - lowestrank ) > 0.01 ) break; rnd_k++; } wxLogMessage( _T("number of lowestrank alliances with same rank=%d"), rnd_k ); alliances[my_random( rnd_k )].AddAlliance( clan ); ++clan_it; } } for ( size_t i = 0; i < players_sorted.size(); ++i ) { // skip clanners, those have been added already. if ( clan_alliances.count( players_sorted[i]->GetClan() ) > 0 ) { wxLogMessage( _T("clanner already added, nick=%s"), players_sorted[i]->GetNick().c_str() ); continue; } // find alliances with lowest ranksum // insert current user into random one out of them // since performance doesnt matter here, i simply sort alliances, // then find how many alliances in beginning have lowest ranksum // note that balance player ranks range from 1 to 1.1 now // i.e. them are quasi equal // so we're essentially adding to alliance with smallest number of players, // the one with smallest ranksum. std::sort( alliances.begin(), alliances.end() ); float lowestrank = alliances[0].ranksum; int rnd_k = 1;// number of alliances with rank equal to lowestrank while ( size_t( rnd_k ) < alliances.size() ) { if ( fabs( alliances[rnd_k].ranksum - lowestrank ) > 0.01 ) break; rnd_k++; } wxLogMessage( _T("number of lowestrank alliances with same rank=%d"), rnd_k ); alliances[my_random( rnd_k )].AddPlayer( players_sorted[i] ); } UserList::user_map_t::size_type totalplayers = GetNumUsers(); for ( size_t i = 0; i < alliances.size(); ++i ) { for ( size_t j = 0; j < alliances[i].players.size(); ++j ) { ASSERT_LOGIC( alliances[i].players[j], _T("fail in Autobalance, NULL player") ); int balanceteam = alliances[i].players[j]->BattleStatus().team; wxLogMessage( _T("setting team %d to alliance %d"), balanceteam, i ); for ( size_t h = 0; h < totalplayers; h++ ) // change ally num of all players in the team { User& usr = GetUser( h ); if ( usr.BattleStatus().team == balanceteam ) ForceAlly( usr, alliances[i].allynum ); } } } }
inline void Draw( const TextureHandle& texture ) { m_pImpl->Draw( 0, GetNumRects(), texture ); }
/// renders all the rects inline void Draw() { SetBasicRenderStates(); m_pImpl->Draw( 0, GetNumRects() ); }
/// renders all the rects with the current render states inline void draw() { m_pImpl->draw( 0, GetNumRects() ); }