bygfoot/src/game.c

213 lines
6.7 KiB
C

#include "fixture.h"
#include "game.h"
#include "maths.h"
#include "option.h"
#include "player.h"
#include "team.h"
#include "user.h"
#include "variables.h"
/** How the cskill of field players get weighted for the team values in
a match. Rows are player position, columns value type.
@see game_get_player_contribution() */
gfloat player_weights[3][3] =
{{1, 0.4, 0.25},
{0.625, 1, 0.625},
{0.2, 0.6, 1.3}};
/** Calculate attacking, defending and goalie values for the two teams
of a fixture.
@param fix The fixture we calculate.
@param team_value The place to store the values.
@param home_advantage The home advantage factor.
@see #GameTeamValue
*/
void
game_get_values(const Fixture *fix, gfloat team_values[][GAME_TEAM_VALUE_END],
gfloat home_advantage)
{
gint i, j;
Team *tm[2] = {fix->teams[0], fix->teams[1]};
gfloat style_factor;
/*d*/
/* printf("\nhome %.2f\n", home_advantage); */
for(i=0;i<2;i++)
{
for(j=0;j<GAME_TEAM_VALUE_END;j++)
team_values[i][j] = 0;
style_factor = (gfloat)tm[i]->style * const_float("float_game_style_factor");
team_values[i][GAME_TEAM_VALUE_GOALIE] =
game_get_player_contribution(player_of(tm[i], 0), FALSE) *
(1 + home_advantage * (i == 0)) *
(1 + const_float("float_player_boost_skill_effect") *
(team_is_user(tm[i]) != -1 &&
option_int("int_opt_user_boost", usr(team_is_user(tm[i])).options) == 1));
for(j=1;j<11;j++)
{
team_values[i][GAME_TEAM_VALUE_ATTACK] +=
game_get_player_contribution(player_of(tm[i], j), GAME_TEAM_VALUE_ATTACK);
team_values[i][GAME_TEAM_VALUE_MIDFIELD] +=
game_get_player_contribution(player_of(tm[i], j), GAME_TEAM_VALUE_MIDFIELD);
team_values[i][GAME_TEAM_VALUE_DEFEND] +=
game_get_player_contribution(player_of(tm[i], j), GAME_TEAM_VALUE_DEFEND);
}
team_values[i][GAME_TEAM_VALUE_ATTACK] *=
((1 + style_factor) * (1 + home_advantage * (i == 0)) *
(1 + const_float("float_player_boost_skill_effect") *
(team_is_user(tm[i]) != -1 &&
option_int("int_opt_user_boost", usr(team_is_user(tm[i])).options) == 1)));
team_values[i][GAME_TEAM_VALUE_DEFEND] *=
((1 - style_factor) * (1 + home_advantage * (i == 0)) *
(1 + const_float("float_player_boost_skill_effect") *
(team_is_user(tm[i]) != -1 &&
option_int("int_opt_user_boost", usr(team_is_user(tm[i])).options) == 1)));
}
}
/** Return the contribution of a player to the attack, midfield or defend.
@param pl The player.
@param type Whether we have defend, midfield or attack value.
@return The player's contribution depending on position and
fitness. */
gfloat
game_get_player_contribution(const Player *pl, gint type)
{
return (gfloat)(pl->cskill * powf((gfloat)pl->fitness / 100,
const_float("float_player_fitness_exponent")) *
player_weights[pl->cpos - 1][type - GAME_TEAM_VALUE_DEFEND]);
}
/** Return a random attacking or defending player
or the player that has to shoot the number_of_penalty'th penalty.
@param tm The team we examine.
@param player_type Whether we concentrate on attacking or defending players
or would like to have a penalty shooting player.
@param last_penalty The player that shot the last penalty.
@param not_this_one A player to exclude.
@param skills Whether to weight with skills, too.
@return A player index. */
gint
game_get_player(const Team *tm, gint player_type,
gint last_penalty, gint not_this_one,
gboolean skills)
{
gint i, player = not_this_one;
gfloat weights[3];
gfloat probs[10];
gfloat rndom;
if(player_type == GAME_PLAYER_TYPE_ATTACK)
{
weights[0] = 0.25;
weights[1] = 0.5;
weights[2] = 1;
}
else if(player_type == GAME_PLAYER_TYPE_MIDFIELD)
{
weights[0] = 0.5;
weights[1] = 1;
weights[2] = 0.5;
}
else if(player_type == GAME_PLAYER_TYPE_DEFEND)
{
weights[0] = 1;
weights[1] = 0.5;
weights[2] = 0.25;
}
else if(player_type == GAME_PLAYER_TYPE_INJURY)
weights[0] = -1;
else if(player_type == GAME_PLAYER_TYPE_PENALTY)
return game_get_penalty_taker(tm, last_penalty);
game_get_player_probs(tm->players, probs, weights, skills);
while(player == not_this_one)
{
rndom = math_rnd(0, probs[9]);
if(rndom < probs[0])
player = player_of(tm, 1)->id;
else
for(i=1;i<10;i++)
if(rndom < probs[i] && rndom > probs[i - 1])
player = player_of(tm, i + 1)->id;
}
return player;
}
/** Write the probabilities for field players being picked
(e.g. a random defender, or a player who gets injured) into
the float array. Depends on skill mostly.
@param players Player array.
@param probs Array with probabilities that gets filled.
@param weights How to weight the players depending on their position.
@param skills Whether to weight with skills, too. */
void
game_get_player_probs(GArray *players, gfloat *probs, gfloat *weights, gboolean skills)
{
gint i;
if(weights[0] == -1)
for(i=0;i<10;i++)
probs[i] = 1;
else
{
probs[0] = (skills) ? (gfloat)g_array_index(players, Player, 1).cskill *
powf((gfloat)g_array_index(players, Player, 1).fitness,
const_float("float_player_fitness_exponent")) *
weights[g_array_index(players, Player, 1).pos - 1] :
weights[g_array_index(players, Player, 1).pos - 1];
for(i=1;i<10;i++)
probs[i] = probs[i - 1] +
((skills) ? (gfloat)g_array_index(players, Player, i + 1).cskill *
powf((gfloat)g_array_index(players, Player, i + 1).fitness,
const_float("float_player_fitness_exponent")) *
weights[g_array_index(players, Player, i + 1).pos - 1] :
weights[g_array_index(players, Player, i + 1).pos - 1]);
}
}
/** Return the player who's shooting the following penalty
(at penalty shoot-out).
@param tm The team that has the penalty.
@param last_penalty The player that shot the last penalty.
@return A player id. */
gint
game_get_penalty_taker(const Team *tm, gint last_penalty)
{
gint i;
GPtrArray *players = g_ptr_array_new();
for(i=0;i<11;i++)
if(player_of(tm, i)->cskill != 0)
g_ptr_array_add(players, player_of(tm, i));
g_ptr_array_sort_with_data(players, (GCompareDataFunc)player_compare_func,
GINT_TO_POINTER(PLAYER_COMPARE_ATTRIBUTE_GAME_SKILL));
if(last_penalty == -1 ||
last_penalty == ((Player*)g_ptr_array_index(players, players->len - 1))->id)
return ((Player*)g_ptr_array_index(players, 0))->id;
for(i=0;i<players->len - 1;i++)
if(last_penalty == ((Player*)g_ptr_array_index(players, i))->id)
return ((Player*)g_ptr_array_index(players, i + 1))->id;
return -1;
}
/** Calculate the number of spectators.
@param fix The fixture we examine. */
void
game_calculate_attendance(Fixture *fix)
{
/*d*/
fix->attendance = 1000;
}