1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
|
//-----------------------------------------------------------------------------
/** @file libpentobi_base/ScoreUtil.h
@author Markus Enzenberger
@copyright GNU General Public License version 3 or later */
//-----------------------------------------------------------------------------
#ifndef LIBPENTOBI_BASE_SCORE_UTIL_H
#define LIBPENTOBI_BASE_SCORE_UTIL_H
#include <algorithm>
#include <array>
#include "Color.h"
#include "PieceInfo.h"
namespace libpentobi_base {
//-----------------------------------------------------------------------------
/** Convert the result of a multi-player game into a comparable number.
This generalizes the game result of a two-player game (0,0.5,1 for
loss/tie/win) for a game with n \> 2 players. The points are sorted in
ascending order. Each rank r_i (i in 0..n-1) is assigned a value of
r_i/(n-1). If multiple players have the same points, the result value is
the average of all ranks with these points. So being the single winner
still gives the result 1 and being the single loser the result 0. Being the
single winner is better than sharing the best rank, which is better than
getting the second rank, etc.
@return The game result for each player. */
template<typename FLOAT>
void get_multiplayer_result(unsigned nu_players,
array<ScoreType, Color::range>& points,
array<FLOAT, Color::range>& result,
bool break_ties)
{
array<ScoreType, Color::range> sorted;
for (Color::IntType i = 0; i < nu_players; ++i)
{
if (break_ties)
// Favor later player. The adjustment must be smaller than the
// smallest difference in points (0.5 for GembloQ).
points[i] += 0.001f * i;
sorted[i] = points[i];
}
// Disable false-positive GCC warning if compiled with -O2
// (last tested with GCC 13.2.0)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Warray-bounds"
sort(sorted.begin(), sorted.begin() + nu_players);
#pragma GCC diagnostic pop
for (Color::IntType i = 0; i < nu_players; ++i)
{
FLOAT sum = 0;
FLOAT n = 0;
FLOAT float_j = 0;
FLOAT factor = 1 / FLOAT(nu_players - 1);
for (unsigned j = 0; j < nu_players; ++j)
{
if (sorted[j] == points[i])
{
sum += factor * float_j;
++n;
}
++float_j;
}
result[i] = sum / n;
}
}
//-----------------------------------------------------------------------------
} // namespace libpentobi_base
#endif // LIBPENTOBI_BASE_SCORE_UTIL_H
|