std::string map_data_common_t::extended_description() const { std::stringstream ss; ss << "<header>" << string_format( _( "That is a %s." ), name().c_str() ) << "</header>" << '\n'; ss << description << std::endl; bool has_any_harvest = std::any_of( harvest_by_season.begin(), harvest_by_season.end(), []( const harvest_id & hv ) { return !hv.obj().empty(); } ); if( has_any_harvest ) { ss << "--" << std::endl; int player_skill = g->u.get_skill_level( skill_survival ); ss << _( "You could harvest the following things from it:" ) << std::endl; // Group them by identical ids to avoid repeating same blocks of data // First, invert the mapping: season->id to id->seasons std::multimap<harvest_id, season_type> identical_harvest; for( size_t season = SPRING; season <= WINTER; season++ ) { const auto &hv = harvest_by_season[ season ]; if( hv.obj().empty() ) { continue; } identical_harvest.insert( std::make_pair( hv, static_cast<season_type>( season ) ) ); } // Now print them in order of seasons // @todo: Highlight current season for( size_t season = SPRING; season <= WINTER; season++ ) { const auto range = identical_harvest.equal_range( harvest_by_season[ season ] ); if( range.first == range.second ) { continue; } // List the seasons first ss << enumerate_as_string( range.first, range.second, []( const std::pair<harvest_id, season_type> &pr ) { if( pr.second == season_of_year( calendar::turn ) ) { return "<good>" + calendar::name_season( pr.second ) + "</good>"; } return "<dark>" + calendar::name_season( pr.second ) + "</dark>"; } ); ss << ":" << std::endl; // List the drops // They actually describe what player can get from it now, so it isn't spoily // @todo: Allow spoily listing of everything ss << range.first->first.obj().describe( player_skill ) << std::endl; // Remove the range from the multimap so that it isn't listed twice identical_harvest.erase( range.first, range.second ); } ss << std::endl; } return replace_colors( ss.str() ); }
/** Reduces the number of 4-color palettes in the image described by \a buf, \a width and \a height. Updates unique_pals to reflect the new palette usage. Updates \a pal_indexes to reflect the new palette usage. Updates \a buf to reflect the new palette usage. */ static void reduce_palettes(unsigned char *buf, int width, int height, const unsigned char *pal_data, const int *pal_sizes, int *unique_pals, int *unique_pals_count, int *pal_indexes) { int i, j; int upc = *unique_pals_count; if (upc <= 4) return; /* nothing to do */ int cw = width / 16; int ch = height / 16; /* count palette frequencies */ int *pal_freqs = (int*)calloc(upc, sizeof(int)); for (i = 0; i < cw * ch; ++i) ++pal_freqs[pal_indexes[i]]; while (upc > 4) { int pi1 = -1; int pi2 = -1; int diff = INT_MAX; #if 0 printf("reducing from %d palettes\n", upc); printf("before:\n"); for (int v = 0; v < upc; ++v) { printf(" %d: %d\t", v, pal_freqs[v]); for (int f = 0; f < pal_sizes[unique_pals[v]]; ++f) printf(" %.2X", pal_data[unique_pals[v]*4 + f]); printf("\n"); } for (int w = 0; w < cw*ch; ++w) printf("%d ", pal_indexes[w]); printf("\n"); #endif /* find the two palettes that are most similar */ for (i = 0; i < upc; ++i) { const unsigned char *p1 = &pal_data[unique_pals[i] * 4]; int s1 = pal_sizes[unique_pals[i]]; for (j = i + 1; j < upc; ++j) { const unsigned char *p2 = &pal_data[unique_pals[j] * 4]; int s2 = pal_sizes[unique_pals[j]]; int d = nes_palettes_diff(p1, s1, p2, s2); if (d <= diff) { if ((pi1 == -1) || (pal_freqs[i] < pal_freqs[pi1]) || (pal_freqs[j] < pal_freqs[pi2]) || (pal_freqs[j] < pal_freqs[pi1]) || (pal_freqs[i] < pal_freqs[pi2])) { diff = d; pi1 = i; pi2 = j; } } } } if (pal_freqs[pi1] > pal_freqs[pi2]) { int tmp = pi1; pi1 = pi2; pi2 = tmp; } /* replace pi1 by pi2 */ // printf("replacing %d by %d\n", pi1, pi2); const unsigned char *dest_pal = &pal_data[unique_pals[pi2]*4]; int dest_pal_sz = pal_sizes[unique_pals[pi2]]; for (i = 0; i < ch; ++i) { for (j = 0; j < cw; ++j) { int k = i*cw + j; if (pal_indexes[k] == pi1) { pal_indexes[k] = pi2; if (pi2 > pi1) --pal_indexes[k]; /* because pi1 will be removed from the array */ ++pal_freqs[pi2]; --pal_freqs[pi1]; /* replace colors so that only colors in target palette are used */ replace_colors(&buf[(i*width*16)+(j*16)], 16, 16, width, dest_pal, dest_pal_sz); } else if (pal_indexes[k] > pi1) { --pal_indexes[k]; } } } assert(pal_freqs[pi1] == 0); /* kill the unique_pals entry */ memmove(&unique_pals[pi1], &unique_pals[pi1+1], (upc-(pi1+1))*sizeof(int)); memmove(&pal_freqs[pi1], &pal_freqs[pi1+1], (upc-(pi1+1))*sizeof(int)); --upc; } *unique_pals_count = upc; #if 0 printf("after:\n"); for (int v = 0; v < upc; ++v) { printf(" %d: %d\t", v, pal_freqs[v]); for (int f = 0; f < pal_sizes[unique_pals[v]]; ++f) printf(" %.2X", pal_data[unique_pals[v]*4 + f]); printf("\n"); } for (int w = 0; w < cw*ch; ++w) printf("%d ", pal_indexes[w]); printf("\n"); #endif free(pal_freqs); }