bygfoot/src/game.c

1263 lines
40 KiB
C
Raw Normal View History

2005-10-20 17:45:00 +02:00
/*
game.c
2005-11-26 17:52:51 +01:00
Bygfoot Football Manager -- a small and simple GTK2-based
football management game.
2005-10-20 17:45:00 +02:00
http://bygfoot.sourceforge.net
2005-10-20 17:45:00 +02:00
Copyright (C) 2005 Gyözö Both (gyboth@bygfoot.com)
2005-10-20 17:45:00 +02:00
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
2005-10-20 17:45:00 +02:00
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
2005-10-20 17:45:00 +02:00
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
2005-10-20 17:45:00 +02:00
*/
2005-03-16 21:48:25 +01:00
#include "cup.h"
#include "finance.h"
2005-01-09 21:21:22 +01:00
#include "fixture.h"
#include "game.h"
2005-03-08 09:25:46 +01:00
#include "game_gui.h"
2005-03-16 21:48:25 +01:00
#include "league.h"
2005-03-11 13:17:48 +01:00
#include "live_game.h"
2005-06-16 08:56:12 +02:00
#include "main.h"
2005-01-09 21:21:22 +01:00
#include "maths.h"
2005-03-08 09:25:46 +01:00
#include "misc.h"
#include "option.h"
2005-01-09 21:21:22 +01:00
#include "player.h"
2005-03-13 16:46:15 +01:00
#include "table.h"
2005-01-09 21:21:22 +01:00
#include "team.h"
2005-03-08 09:25:46 +01:00
#include "treeview.h"
#include "user.h"
2005-01-09 21:21:22 +01:00
#include "variables.h"
/** 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)
{
#ifdef DEBUG
printf("game_get_values\n");
#endif
2005-01-09 21:21:22 +01:00
gint i, j;
Team *tm[2] = {fix->teams[0], fix->teams[1]};
gfloat style_factor;
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");
2005-01-09 21:21:22 +01:00
team_values[i][GAME_TEAM_VALUE_GOALIE] =
2008-11-06 11:01:28 +01:00
player_get_game_skill(player_of_idx_team(tm[i], 0), FALSE, TRUE) *
(1 + home_advantage * (i == 0));
2005-01-09 21:21:22 +01:00
for(j=1;j<11;j++)
2005-10-24 22:50:48 +02:00
if(player_of_idx_team(tm[i], j)->cskill > 0)
{
team_values[i][GAME_TEAM_VALUE_ATTACK] +=
game_get_player_contribution(player_of_idx_team(tm[i], j),
GAME_TEAM_VALUE_ATTACK, TRUE);
2005-10-24 22:50:48 +02:00
team_values[i][GAME_TEAM_VALUE_MIDFIELD] +=
game_get_player_contribution(player_of_idx_team(tm[i], j),
GAME_TEAM_VALUE_MIDFIELD, TRUE);
2005-10-24 22:50:48 +02:00
team_values[i][GAME_TEAM_VALUE_DEFEND] +=
game_get_player_contribution(player_of_idx_team(tm[i], j),
GAME_TEAM_VALUE_DEFEND, TRUE);
2005-10-24 22:50:48 +02:00
}
2005-01-09 21:21:22 +01:00
2005-03-08 09:25:46 +01:00
for(j=GAME_TEAM_VALUE_DEFEND;j<GAME_TEAM_VALUE_DEFEND + 3;j++)
team_values[i][j] *=
((1 + home_advantage * (i == 0)));
2005-03-08 09:25:46 +01:00
2005-03-25 21:18:35 +01:00
team_values[i][GAME_TEAM_VALUE_DEFEND] *= (1 - style_factor);
team_values[i][GAME_TEAM_VALUE_ATTACK] *= (1 + style_factor);
2005-03-08 09:25:46 +01:00
}
2005-01-09 21:21:22 +01:00
}
2005-01-24 19:01:55 +01:00
/** Return the contribution of a player to the attack, midfield or defend.
2005-01-09 21:21:22 +01:00
@param pl The player.
2005-01-24 19:01:55 +01:00
@param type Whether we have defend, midfield or attack value.
@param special Whether to count special influence like boost and
streak.
2005-01-09 21:21:22 +01:00
@return The player's contribution depending on position and
fitness. */
gfloat
game_get_player_contribution(const Player *pl, gint type, gboolean special)
2005-01-09 21:21:22 +01:00
{
2005-03-08 09:25:46 +01:00
/** 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] =
{{const_float_fast(float_player_team_weight_defender_defense),
const_float_fast(float_player_team_weight_defender_midfield),
const_float_fast(float_player_team_weight_defender_attack)},
{const_float_fast(float_player_team_weight_midfielder_defense),
const_float_fast(float_player_team_weight_midfielder_midfield),
const_float_fast(float_player_team_weight_midfielder_attack)},
{const_float_fast(float_player_team_weight_forward_defense),
const_float_fast(float_player_team_weight_forward_midfield),
const_float_fast(float_player_team_weight_forward_attack)}};
2005-03-08 09:25:46 +01:00
return player_get_game_skill(pl, FALSE, special) *
2005-10-24 22:50:48 +02:00
player_weights[pl->cpos - 1][type - GAME_TEAM_VALUE_DEFEND];
2005-01-09 21:21:22 +01:00
}
/** 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.
2005-01-09 21:21:22 +01:00
@param not_this_one A player to exclude.
2005-01-24 19:01:55 +01:00
@param skills Whether to weight with skills, too.
2005-01-09 21:21:22 +01:00
@return A player index. */
gint
2005-01-24 19:01:55 +01:00
game_get_player(const Team *tm, gint player_type,
gint last_penalty, gint not_this_one,
2005-01-24 19:01:55 +01:00
gboolean skills)
2005-01-09 21:21:22 +01:00
{
#ifdef DEBUG
printf("game_get_player\n");
#endif
2005-01-09 21:21:22 +01:00
gint i, player = not_this_one;
gfloat weights[3];
gfloat probs[10];
gfloat rndom;
2005-01-24 19:01:55 +01:00
if(player_type == GAME_PLAYER_TYPE_ATTACK)
2005-01-09 21:21:22 +01:00
{
2005-07-02 13:06:43 +02:00
weights[0] = const_float("float_game_player_weight_attack_def");
weights[1] = const_float("float_game_player_weight_attack_mid");
weights[2] = const_float("float_game_player_weight_attack_fwd");
2005-01-09 21:21:22 +01:00
}
2005-01-24 19:01:55 +01:00
else if(player_type == GAME_PLAYER_TYPE_MIDFIELD)
2005-01-09 21:21:22 +01:00
{
2005-07-02 13:06:43 +02:00
weights[0] = const_float("float_game_player_weight_midfield_def");
weights[1] = const_float("float_game_player_weight_midfield_mid");
weights[2] = const_float("float_game_player_weight_midfield_fwd");
2005-01-09 21:21:22 +01:00
}
2005-01-24 19:01:55 +01:00
else if(player_type == GAME_PLAYER_TYPE_DEFEND)
2005-01-09 21:21:22 +01:00
{
2005-07-02 13:06:43 +02:00
weights[0] = const_float("float_game_player_weight_defend_def");
weights[1] = const_float("float_game_player_weight_defend_mid");
weights[2] = const_float("float_game_player_weight_defend_fwd");
2005-01-09 21:21:22 +01:00
}
else if(player_type == GAME_PLAYER_TYPE_PENALTY)
return game_get_penalty_taker(tm, last_penalty);
2005-03-09 14:10:28 +01:00
else
2005-10-24 22:50:48 +02:00
main_exit_program(EXIT_INT_NOT_FOUND,
"game_get_player: unknown player type %d\n", player_type);
2005-01-09 21:21:22 +01:00
2005-01-24 19:01:55 +01:00
game_get_player_probs(tm->players, probs, weights, skills);
2005-01-09 21:21:22 +01:00
2005-03-09 14:10:28 +01:00
if(probs[9] > 0)
{
while(player == not_this_one)
{
rndom = math_rnd(0, probs[9]);
if(rndom < probs[0])
2005-04-13 15:01:59 +02:00
player = player_of_idx_team(tm, 1)->id;
2005-03-09 14:10:28 +01:00
else
for(i=1;i<10;i++)
if(rndom < probs[i] && rndom > probs[i - 1])
2005-04-13 15:01:59 +02:00
player = player_of_idx_team(tm, i + 1)->id;
2005-03-09 14:10:28 +01:00
}
}
else
2005-01-09 21:21:22 +01:00
{
2009-04-29 19:18:54 +02:00
debug_print_message("game_get_player: All players injured or banned, apparently.\n");
2005-12-14 15:05:59 +01:00
g_print("%s %s player list:\n", league_cup_get_name_string(tm->clid), tm->name);
2005-03-13 22:10:19 +01:00
for(i=0;i<tm->players->len;i++)
{
if(i < 10)
2005-12-14 15:05:59 +01:00
g_print("prob %.3f ", probs[i]);
g_print("%d %20s health %d cskill %.2f\n", i, player_of_idx_team(tm, i)->name,
player_of_idx_team(tm, i)->health, player_of_idx_team(tm, i)->cskill);
2005-03-13 22:10:19 +01:00
}
2005-06-16 08:56:12 +02:00
2005-06-17 14:57:05 +02:00
main_exit_program(EXIT_INT_NOT_FOUND, NULL);
2005-03-09 14:10:28 +01:00
return -1;
2005-01-09 21:21:22 +01:00
}
return player;
}
2005-01-24 19:01:55 +01:00
/** 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. */
2005-01-09 21:21:22 +01:00
void
2005-01-24 19:01:55 +01:00
game_get_player_probs(GArray *players, gfloat *probs, gfloat *weights, gboolean skills)
2005-01-09 21:21:22 +01:00
{
#ifdef DEBUG
printf("game_get_player_probs\n");
#endif
2005-01-09 21:21:22 +01:00
gint i;
probs[0] = (skills) ?
player_get_game_skill(&g_array_index(players, Player, 1), FALSE, TRUE) *
2005-07-18 21:53:40 +02:00
weights[g_array_index(players, Player, 1).cpos - 1] :
weights[g_array_index(players, Player, 1).cpos - 1] *
2005-03-09 14:10:28 +01:00
(g_array_index(players, Player, 1).cskill != 0);
probs[0] *= (1 + (gfloat)g_array_index(players, Player, 1).streak *
const_float_fast(float_player_streak_influence_skill));
2005-03-09 14:10:28 +01:00
for(i=1;i<10;i++)
{
2005-03-09 14:10:28 +01:00
probs[i] = probs[i - 1] +
((skills) ?
player_get_game_skill(&g_array_index(players, Player, i + 1), FALSE, TRUE) *
2005-07-18 21:53:40 +02:00
weights[g_array_index(players, Player, i + 1).cpos - 1] :
weights[g_array_index(players, Player, i + 1).cpos - 1] *
2005-03-09 14:10:28 +01:00
(g_array_index(players, Player, i + 1).cskill != 0));
probs[i] *= (1 + (gfloat)g_array_index(players, Player, i + 1).streak *
const_float_fast(float_player_streak_influence_skill));
}
2005-01-09 21:21:22 +01:00
}
/** 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)
{
#ifdef DEBUG
printf("game_get_penalty_taker\n");
#endif
2005-03-08 09:25:46 +01:00
gint i, return_value = -1;
GPtrArray *players = g_ptr_array_new();
for(i=0;i<11;i++)
2005-04-13 15:01:59 +02:00
if(player_of_idx_team(tm, i)->cskill != 0)
g_ptr_array_add(players, player_of_idx_team(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)
2005-03-08 09:25:46 +01:00
return_value = ((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)
2005-03-08 09:25:46 +01:00
{
return_value = ((Player*)g_ptr_array_index(players, i + 1))->id;
break;
}
g_ptr_array_free(players, TRUE);
2005-03-08 09:25:46 +01:00
return return_value;
}
2005-03-08 09:25:46 +01:00
/** Do some things that have to be done at the beginning of a
game, e.g. calculate attendance etc.
@param fix The fixture we examine. */
void
2005-03-08 09:25:46 +01:00
game_initialize(Fixture *fix)
{
#ifdef DEBUG
printf("game_initialize\n");
#endif
2005-03-08 09:25:46 +01:00
gint i, j;
2005-03-17 21:26:01 +01:00
gint user_idx[2] = {team_is_user(fix->teams[0]), team_is_user(fix->teams[1])};
2005-03-08 09:25:46 +01:00
2005-06-04 12:28:49 +02:00
if(fix->home_advantage)
game_assign_attendance(fix);
else
game_assign_attendance_neutral(fix);
2008-05-04 17:36:30 +02:00
if(!sett_int("int_opt_disable_finances"))
finance_assign_game_money(fix);
2005-03-08 09:25:46 +01:00
for(i=0;i<2;i++)
2005-03-16 21:48:25 +01:00
{
2005-03-13 16:46:15 +01:00
for(j=0;j<fix->teams[i]->players->len;j++)
2005-03-10 21:59:39 +01:00
{
2005-03-13 16:46:15 +01:00
if(j < 11)
{
2005-04-07 23:10:31 +02:00
if(g_array_index(fix->teams[i]->players, Player, j).cskill > 0)
2005-05-19 21:43:22 +02:00
{
player_games_goals_set(&g_array_index(fix->teams[i]->players,
Player, j), fix->clid,
2005-05-19 21:43:22 +02:00
PLAYER_VALUE_GAMES, 1);
g_array_index(fix->teams[i]->players, Player, j).
career[PLAYER_VALUE_GAMES]++;
2005-03-13 16:46:15 +01:00
g_array_index(fix->teams[i]->players, Player, j).
participation = TRUE;
2005-07-08 11:26:00 +02:00
if(query_player_is_youth((&g_array_index(fix->teams[i]->players,
Player, j))))
2005-07-08 11:26:00 +02:00
g_array_index(fix->teams[i]->players, Player, j).lsu +=
const_float("float_youth_lsu_addition_match");
player_streak_add_to_prob(
&g_array_index(fix->teams[i]->players, Player, j),
const_float("float_player_streak_add_startup"));
2005-06-20 14:46:57 +02:00
}
2005-04-09 21:18:28 +02:00
}
else
player_streak_add_to_prob(
&g_array_index(fix->teams[i]->players, Player, j),
const_float("float_player_streak_add_no_startup"));
2005-03-10 21:59:39 +01:00
}
2005-03-16 21:48:25 +01:00
2005-03-17 21:26:01 +01:00
if(user_idx[i] != -1)
{
2005-04-06 00:10:18 +02:00
usr(user_idx[i]).counters[COUNT_USER_SHOW_RES] = 1;
2005-03-17 21:26:01 +01:00
}
2005-03-16 21:48:25 +01:00
}
}
/** Find out how many spectators there were,
depending on safety of the stadium etc.
@param fix The match we examine. */
void
game_assign_attendance(Fixture *fix)
{
#ifdef DEBUG
printf("game_assign_attendance\n");
#endif
2005-03-16 21:48:25 +01:00
Team *tm[2] = {fix->teams[0], fix->teams[1]};
gfloat factor =
math_rnd(const_float("float_game_stadium_attendance_percentage_lower"),
const_float("float_game_stadium_attendance_percentage_upper")) *
powf(tm[0]->stadium.safety,
const_float("float_game_stadium_attendance_safety_exponent"));
2005-03-19 21:04:08 +01:00
gint max_att = MIN((gint)rint((gfloat)league_cup_average_capacity(tm[0]->clid) *
2005-05-13 20:20:47 +02:00
const_float("float_game_stadium_attendance_average_exceed_factor") *
math_rnd(0.9, 1.1)),
2005-03-16 21:48:25 +01:00
tm[0]->stadium.capacity);
if(fix->clid < ID_CUP_START &&
team_get_league_rank(tm[1], fix->clid) <
2005-03-16 21:48:25 +01:00
(gint)rint((gfloat)league_from_clid(fix->clid)->teams->len *
const_float("float_game_stadium_attendance_rank_percentage")))
factor *= const_float("float_game_stadium_attendance_rank_factor");
if(fix->clid >= ID_CUP_START)
{
if(cup_from_clid(fix->clid)->rounds->len - fix->round <=
const_int("int_game_stadium_attendance_cup_rounds_full_house"))
factor = 1;
else if(query_league_cup_has_property(fix->clid, "national"))
2005-03-16 21:48:25 +01:00
factor *= const_float("float_game_stadium_attendance_cup_national_factor");
else
factor *= const_float("float_game_stadium_attendance_cup_international_factor");
}
/* calculate the differnce in ticket prices has on attendance */
gfloat delta_price = tm[0]->stadium.ticket_price - const_int("int_team_stadium_ticket_price");
gfloat price_factor = math_gauss_dist(0.92, 1.08) * 1/(1+const_float("float_team_stadium_price_attendance_factor")*delta_price);
factor = MIN(factor * price_factor, 1);
2005-06-20 16:24:54 +02:00
fix->attendance = MIN(MIN((gint)rint((gfloat)tm[0]->stadium.capacity * factor),
max_att * factor), max_att);
2005-03-16 21:48:25 +01:00
tm[0]->stadium.average_attendance =
(gint)rint((gfloat)(tm[0]->stadium.average_attendance * tm[0]->stadium.games + fix->attendance) /
(gfloat)(tm[0]->stadium.games + 1));
tm[0]->stadium.possible_attendance += tm[0]->stadium.capacity;
tm[0]->stadium.games++;
}
2005-03-08 09:25:46 +01:00
2005-06-04 12:28:49 +02:00
/** Assign attendance for a match on neutral ground. */
void
game_assign_attendance_neutral(Fixture *fix)
{
#ifdef DEBUG
printf("game_assign_attendance_neutral\n");
#endif
2005-06-04 12:28:49 +02:00
const GPtrArray *teamsp =
(GPtrArray*)league_cup_get_teams(fix->clid);
2005-10-27 23:10:15 +02:00
gfloat av_att = (fix->clid >= ID_CUP_START &&
query_league_cup_has_property(fix->clid, "international") && teamsp->len > 0) ?
2005-06-04 12:28:49 +02:00
(gfloat)league_cup_average_capacity(fix->clid) :
(gfloat)league_cup_average_capacity(lig(0).id);
fix->attendance = (gint)rint(av_att *
math_rnd(const_float("float_game_stadium_attendance_neutral_lower"),
const_float("float_game_stadium_attendance_neutral_upper")));
}
2005-03-08 09:25:46 +01:00
/** Save the team states in the current live game
when a pause occurs. */
void
game_save_team_states(void)
{
#ifdef DEBUG
printf("game_save_team_states\n");
#endif
2005-03-08 09:25:46 +01:00
gint i, j;
const Team *teams[2] = {usr(stat2).live_game.fix->teams[0],
usr(stat2).live_game.fix->teams[1]};
for(i=0;i<2;i++)
{
usr(stat2).live_game.team_state[i].structure =
teams[i]->structure;
usr(stat2).live_game.team_state[i].style =
teams[i]->style;
usr(stat2).live_game.team_state[i].boost =
teams[i]->boost;
for(j=0;j<11;j++)
usr(stat2).live_game.team_state[i].player_ids[j] =
2005-04-13 15:01:59 +02:00
player_of_idx_team(teams[i], j)->id;
2005-03-08 09:25:46 +01:00
}
}
/** Check whether the number of substitutions
during a live game pause isn't too high.
@return TRUE if the subs were ok, FALSE else. */
gboolean
game_check_live_game_resume_state(void)
{
#ifdef DEBUG
printf("game_check_live_game_resume_state\n");
#endif
2005-03-08 09:25:46 +01:00
gint i, j;
gint subs[2] = {0, 0};
const Team *teams[2] = {usr(stat2).live_game.fix->teams[0],
usr(stat2).live_game.fix->teams[1]};
gboolean return_value = TRUE;
for(i=0;i<2;i++)
{
for(j=0;j<11;j++)
2005-04-13 15:01:59 +02:00
if(!query_integer_is_in_array(player_of_idx_team(teams[i], j)->id,
2005-03-08 09:25:46 +01:00
usr(stat2).live_game.team_state[i].player_ids,
2005-10-13 10:52:33 +02:00
11))
2005-03-08 09:25:46 +01:00
subs[i]++;
if(subs[i] > usr(stat2).live_game.subs_left[i])
2005-04-26 17:00:26 +02:00
{
game_reset_players(i);
2005-03-08 09:25:46 +01:00
return_value = FALSE;
2005-04-26 17:00:26 +02:00
}
2005-03-08 09:25:46 +01:00
}
return return_value;
}
2005-04-26 17:00:26 +02:00
/** Undo the player swaps the user made during a live game pause.
@param idx The team index in the current live game fixture. */
void
game_reset_players(gint idx)
{
#ifdef DEBUG
printf("game_reset_players\n");
#endif
2005-04-26 17:00:26 +02:00
gint i;
Team *tm = usr(stat2).live_game.fix->teams[idx];
GArray *players = g_array_new(FALSE, FALSE, sizeof(Player));
for(i=0;i<11;i++)
g_array_append_val(players,
*player_of_id_team(tm, usr(stat2).live_game.team_state[idx].player_ids[i]));
for(i=0;i<tm->players->len;i++)
if(!query_integer_is_in_array(player_of_idx_team(tm, i)->id,
usr(stat2).live_game.team_state[idx].player_ids,
2005-10-13 10:52:33 +02:00
11))
2005-04-26 17:00:26 +02:00
g_array_append_val(players, *player_of_idx_team(tm, i));
g_array_free(tm->players, TRUE);
tm->players = players;
team_change_structure(tm, team_find_appropriate_structure(tm));
team_rearrange(tm);
treeview_show_user_player_list();
}
2005-03-08 09:25:46 +01:00
/** Find pairs of substituted players after a live game pause. */
void
game_get_subs(gint team_number, gint *subs_in, gint *subs_out)
{
#ifdef DEBUG
printf("game_get_subs\n");
#endif
2005-03-08 09:25:46 +01:00
gint i, cnt = 0;
const Team *tm = usr(stat2).live_game.fix->teams[team_number];
gint current_players[11];
for(i=0;i<3;i++)
subs_in[i] = subs_out[i] = -1;
for(i=0;i<11;i++)
{
2005-04-13 15:01:59 +02:00
current_players[i] = player_of_idx_team(tm, i)->id;
if(!query_integer_is_in_array(player_of_idx_team(tm, i)->id,
2005-03-08 09:25:46 +01:00
usr(stat2).live_game.team_state[team_number].player_ids,
2005-10-13 10:52:33 +02:00
11))
2005-03-08 09:25:46 +01:00
{
2005-04-13 15:01:59 +02:00
subs_in[cnt] = player_of_idx_team(tm, i)->id;
2005-03-08 09:25:46 +01:00
cnt++;
}
}
cnt = 0;
for(i=0;i<11;i++)
if(!query_integer_is_in_array(usr(stat2).live_game.team_state[team_number].player_ids[i],
2005-10-13 10:52:33 +02:00
current_players, 11))
2005-03-08 09:25:46 +01:00
{
subs_out[cnt] = usr(stat2).live_game.team_state[team_number].player_ids[i];
cnt++;
}
}
2005-03-09 14:10:28 +01:00
/** Choose an injury for a player and adjust health values.
@param pl The player that gets injured. */
void
game_player_injury(Player *pl)
{
#ifdef DEBUG
printf("game_player_injury\n");
#endif
2005-03-09 14:10:28 +01:00
gint i;
gfloat rndom;
/* probabilities of different injuries */
gfloat injury_probs[13]={0,
const_float("float_player_injury_concussion"),
const_float("float_player_injury_pulled_muscle"),
const_float("float_player_injury_hamstring"),
const_float("float_player_injury_groin"),
const_float("float_player_injury_frac_ankle"),
const_float("float_player_injury_rib"),
const_float("float_player_injury_leg"),
const_float("float_player_injury_brok_ankle"),
const_float("float_player_injury_arm"),
const_float("float_player_injury_shoulder"),
const_float("float_player_injury_ligament"),
const_float("float_player_injury_career_stop")};
gint duration[12]={
math_gauss_disti(const_int("int_player_injury_duration_concussion") -
const_int("int_player_injury_duration_dev_concussion"),
const_int("int_player_injury_duration_concussion") +
const_int("int_player_injury_duration_dev_concussion")),
math_gauss_disti(const_int("int_player_injury_duration_pulled_muscle") -
const_int("int_player_injury_duration_dev_pulled_muscle"),
const_int("int_player_injury_duration_pulled_muscle") +
const_int("int_player_injury_duration_dev_pulled_muscle")),
math_gauss_disti(const_int("int_player_injury_duration_hamstring") -
const_int("int_player_injury_duration_dev_hamstring"),
const_int("int_player_injury_duration_hamstring") +
const_int("int_player_injury_duration_dev_hamstring")),
math_gauss_disti(const_int("int_player_injury_duration_groin") -
const_int("int_player_injury_duration_dev_groin"),
const_int("int_player_injury_duration_groin") +
const_int("int_player_injury_duration_dev_groin")),
math_gauss_disti(const_int("int_player_injury_duration_frac_ankle") -
const_int("int_player_injury_duration_dev_frac_ankle"),
const_int("int_player_injury_duration_frac_ankle") +
const_int("int_player_injury_duration_dev_frac_ankle")),
math_gauss_disti(const_int("int_player_injury_duration_rib") -
const_int("int_player_injury_duration_dev_rib"),
const_int("int_player_injury_duration_rib") +
const_int("int_player_injury_duration_dev_rib")),
math_gauss_disti(const_int("int_player_injury_duration_leg") -
const_int("int_player_injury_duration_dev_leg"),
const_int("int_player_injury_duration_leg") +
const_int("int_player_injury_duration_dev_leg")),
math_gauss_disti(const_int("int_player_injury_duration_brok_ankle") -
const_int("int_player_injury_duration_dev_brok_ankle"),
const_int("int_player_injury_duration_brok_ankle") +
const_int("int_player_injury_duration_dev_brok_ankle")),
math_gauss_disti(const_int("int_player_injury_duration_arm") -
const_int("int_player_injury_duration_dev_arm"),
const_int("int_player_injury_duration_arm") +
const_int("int_player_injury_duration_dev_arm")),
math_gauss_disti(const_int("int_player_injury_duration_shoulder") -
const_int("int_player_injury_duration_dev_shoulder"),
const_int("int_player_injury_duration_shoulder") +
const_int("int_player_injury_duration_dev_shoulder")),
math_gauss_disti(const_int("int_player_injury_duration_ligament") -
const_int("int_player_injury_duration_dev_ligament"),
const_int("int_player_injury_duration_ligament") +
2005-04-07 18:44:33 +02:00
const_int("int_player_injury_duration_dev_ligament")),
50};
2005-03-09 14:10:28 +01:00
for(i=1;i<13;i++)
injury_probs[i] += injury_probs[i - 1];
rndom = math_rnd(0, 1);
for(i=1;i<13;i++)
if(rndom >= injury_probs[i - 1] && rndom < injury_probs[i])
{
pl->health = i;
2005-03-14 18:47:27 +01:00
pl->recovery = duration[i - 1] + 1;
2005-03-09 14:10:28 +01:00
pl->cskill = pl->fitness = 0;
}
2005-04-07 18:44:33 +02:00
if(pl->health == PLAYER_INJURY_CAREER_STOP && team_is_user(pl->team) != -1)
user_event_add(&usr(team_is_user(pl->team)),
EVENT_TYPE_PLAYER_CAREER_STOP, pl->id, -1,
2005-04-07 18:44:33 +02:00
NULL, NULL);
player_streak_add_to_prob(
pl, const_float("float_player_streak_add_injury"));
if(pl->streak == PLAYER_STREAK_HOT)
{
pl->streak = PLAYER_STREAK_NONE;
player_streak_reset_count(pl);
}
2005-03-09 14:10:28 +01:00
}
2009-03-08 12:34:30 +01:00
/** Calculate the probability of a foul event occurring. */
gfloat
game_get_foul_prob(const LiveGame *live_game, const LiveGameUnit *unit)
{
gfloat prob;
gint i;
/* Base probability (a linear function of match time). */
prob = const_float("float_live_game_foul_base") +
const_float("float_live_game_foul_max_inc") * MIN(1, (gfloat)(unit->minute) / 90);
/* Add possible boost influence of the team not in possession. */
prob *= (1 + live_game->fix->teams[!unit->possession]->boost *
const_float("float_team_boost_foul_factor"));
/* Reduce probability depending on the current cards of
the team not in possession, except if their boost is on. */
if(live_game->fix->teams[!unit->possession]->boost != 1)
{
for(i = 0; i < 11; i++)
if(g_array_index(live_game->fix->teams[!unit->possession]->players, Player, i).card_status ==
PLAYER_CARD_STATUS_YELLOW)
prob *= (1 - const_float("float_live_game_foul_prob_reduction_yellow"));
else if(g_array_index(live_game->fix->teams[!unit->possession]->players, Player, i).card_status ==
PLAYER_CARD_STATUS_RED)
prob *= (1 - const_float("float_live_game_foul_prob_reduction_red"));
}
return prob;
}
2005-03-09 14:10:28 +01:00
/** Return a factor influencing who's fouled whom
depending on the states of the team boosts.
@param boost1 Boost of the team in possession.
@param boost2 Boost of the team not in possession.
@return A factor.
*/
gfloat
game_get_foul_possession_factor(gint boost1, gint boost2)
{
#ifdef DEBUG
printf("game_get_foul_possession_factor\n");
#endif
2005-03-09 14:10:28 +01:00
if(boost1 == boost2)
return 1;
if(abs(boost1 - boost2) == 1)
return 1 + const_float("float_team_boost_foul_by_possession_factor1") *
(1 - 2 * (boost1 < boost2));
return 1 + const_float("float_team_boost_foul_by_possession_factor2") *
(1 - 2 * (boost1 < boost2));
}
2005-03-08 09:25:46 +01:00
/** Substitute a player during a match.
@param tm The team we work on.
@param player_number The index of the player. */
gint
game_substitute_player(Team *tm, gint player_number)
{
#ifdef DEBUG
printf("game_substitute_player\n");
#endif
gint i, substitute = -1;
2005-03-08 09:25:46 +01:00
GPtrArray *substitutes = g_ptr_array_new();
gboolean adapt_structure;
for(i=11;i<tm->players->len;i++)
2005-04-07 23:10:31 +02:00
if(g_array_index(tm->players, Player, i).cskill > 0)
g_ptr_array_add(substitutes, &g_array_index(tm->players, Player, i));
2005-03-08 09:25:46 +01:00
2005-10-27 23:10:15 +02:00
if(substitutes->len == 0)
{
g_ptr_array_free(substitutes, TRUE);
2009-04-29 19:18:54 +02:00
debug_print_message("game_substitute_player: no suitable substitutes found (all injured/banned?)");
2005-10-27 23:10:15 +02:00
return -1;
}
g_ptr_array_sort_with_data(substitutes,
(GCompareDataFunc)player_compare_substitute_func,
GINT_TO_POINTER(player_of_idx_team(tm,
player_number)->cpos));
2005-03-08 09:25:46 +01:00
adapt_structure =
2005-03-09 14:10:28 +01:00
(math_get_place(team_find_appropriate_structure(tm), 1) +
math_get_place(team_find_appropriate_structure(tm), 2) +
math_get_place(team_find_appropriate_structure(tm), 3) != 10 ||
(player_of_idx_team(tm, player_number)->cpos !=
((Player*)g_ptr_array_index(substitutes, 0))->pos &&
2005-03-13 22:10:19 +01:00
player_substitution_good_structure(tm->structure,
2005-04-13 15:01:59 +02:00
player_of_idx_team(tm, player_number)->cpos,
2005-03-13 22:10:19 +01:00
((Player*)g_ptr_array_index(substitutes, 0))->pos)));
2005-03-08 09:25:46 +01:00
substitute = ((Player*)g_ptr_array_index(substitutes, 0))->id;
2005-03-13 16:46:15 +01:00
player_swap(tm, player_number, tm, player_id_index(tm, substitute,TRUE));
2005-03-08 09:25:46 +01:00
g_ptr_array_free(substitutes, TRUE);
if(adapt_structure)
{
team_change_structure(tm, team_find_appropriate_structure(tm));
team_rearrange(tm);
}
2005-03-18 23:03:23 +01:00
if(team_is_user(tm) == cur_user)
2005-03-08 09:25:46 +01:00
{
2006-06-29 18:06:52 +02:00
game_gui_write_av_skills(NULL);
2005-03-08 09:25:46 +01:00
2005-07-08 11:26:00 +02:00
selected_row = -1;
2005-03-24 21:22:44 +01:00
treeview_show_user_player_list();
2005-03-08 09:25:46 +01:00
}
return substitute;
}
2005-03-09 14:10:28 +01:00
/** Find out whether we substitute a player to balance
a team after a red card.
2005-05-16 16:44:13 +02:00
@param clid The cup/league id of the fixture.
2005-03-09 14:10:28 +01:00
@param tm The team.
@return A player index or -1 if we don't substitute.
*/
gint
2005-05-16 16:44:13 +02:00
game_find_to_substitute(gint clid, const Team *tm)
2005-03-09 14:10:28 +01:00
{
#ifdef DEBUG
printf("game_find_to_substitute\n");
#endif
2005-03-09 14:10:28 +01:00
gint i;
gint position_to_substitute = -1;
GPtrArray *players = g_ptr_array_new();
gint return_value = -1;
gint current_structure = team_find_appropriate_structure(tm);
gint num_forw = current_structure % 10,
num_mid = math_get_place(current_structure, 2),
num_def = math_get_place(current_structure, 3);
for(i=0;i<11;i++)
2005-05-28 12:41:53 +02:00
if(player_is_banned(player_of_idx_team(tm, i)) <= 0)
2005-04-13 15:01:59 +02:00
g_ptr_array_add(players, player_of_idx_team(tm, i));
2005-03-09 14:10:28 +01:00
g_ptr_array_sort_with_data(players, (GCompareDataFunc)player_compare_func,
GINT_TO_POINTER(PLAYER_COMPARE_ATTRIBUTE_GAME_SKILL));
if(num_forw > 1 || MAX(num_mid, num_def) <= 2)
position_to_substitute = PLAYER_POS_FORWARD;
else if(ABS(num_def - num_mid) > 1 ||
(num_forw == 0 && MAX(num_mid, num_def) > 2))
position_to_substitute = (num_def > num_mid) ? PLAYER_POS_DEFENDER : PLAYER_POS_MIDFIELDER;
else
return -1;
for(i=players->len - 1; i >= 0; i--)
if(((Player*)g_ptr_array_index(players, i))->pos == position_to_substitute)
{
return_value = ((Player*)g_ptr_array_index(players, i))->id;
g_ptr_array_free(players, TRUE);
return return_value;
}
g_ptr_array_free(players, TRUE);
return -1;
}
/** Find out how long a player is banned. */
gint
game_player_get_ban_duration(void)
{
#ifdef DEBUG
printf("game_player_get_ban_duration\n");
#endif
2005-03-09 14:10:28 +01:00
gint i;
gfloat rndom;
gfloat duration_probs[6] =
{0,
const_float("float_live_game_ban_1"),
const_float("float_live_game_ban_2"),
const_float("float_live_game_ban_3"),
const_float("float_live_game_ban_4"),
const_float("float_live_game_ban_5")};
for(i=1;i<6;i++)
duration_probs[i] += duration_probs[i - 1];
rndom = math_rnd(0, 1);
for(i=1;i<6;i++)
if(duration_probs[i - 1] < rndom && rndom < duration_probs[i])
2005-03-14 10:29:39 +01:00
return i + 1;
2005-03-09 14:10:28 +01:00
return -1;
}
/** Find out whether we make a sub after a send-off.
2005-05-16 16:44:13 +02:00
@param clid The id of the fixture.
2005-03-09 14:10:28 +01:00
@param tm The team.
@param player The player index.
@param to_substitute The return location for the index of
the player to substitute.
@param substitute The return location for the player who comes into the game. */
void
2005-05-16 16:44:13 +02:00
game_substitute_player_send_off(gint clid, Team *tm, gint player_number,
2005-03-09 14:10:28 +01:00
gint *to_substitute, gint *substitute)
{
#ifdef DEBUG
printf("game_substitute_player_send_off\n");
#endif
2005-03-09 14:10:28 +01:00
gint i;
gint position = -1;
GPtrArray *substitutes = NULL;
gint current_structure = team_find_appropriate_structure(tm);
gint num_forw = current_structure % 10,
num_mid = math_get_place(current_structure, 2),
num_def = math_get_place(current_structure, 3);
2005-05-16 16:44:13 +02:00
*to_substitute = game_find_to_substitute(clid, tm);
2005-03-09 14:10:28 +01:00
if(*to_substitute == -1)
return;
substitutes = g_ptr_array_new();
for(i=11;i<tm->players->len;i++)
2005-06-04 22:22:22 +02:00
if(g_array_index(tm->players, Player, i).cskill > 0)
g_ptr_array_add(substitutes, player_of_idx_team(tm, i));
2005-03-09 14:10:28 +01:00
2005-10-27 23:10:15 +02:00
if(substitutes->len == 0)
{
g_ptr_array_free(substitutes, TRUE);
2009-04-29 19:18:54 +02:00
debug_print_message("game_substitute_player_send_off: no suitable substitutes found (all injured/banned?)");
2005-10-27 23:10:15 +02:00
*to_substitute = -1;
return;
}
2005-03-09 14:10:28 +01:00
if(num_forw == 0 && MAX(num_def, num_mid) > 2)
position = PLAYER_POS_FORWARD;
else
position = (num_def > num_mid) ? PLAYER_POS_MIDFIELDER : PLAYER_POS_DEFENDER;
g_ptr_array_sort_with_data(substitutes, (GCompareDataFunc)player_compare_substitute_func,
GINT_TO_POINTER(position));
2005-03-08 09:25:46 +01:00
2005-03-09 14:10:28 +01:00
*substitute = ((Player*)g_ptr_array_index(substitutes, 0))->id;
player_swap(tm, player_id_index(tm, *to_substitute, TRUE),
tm, player_id_index(tm, *substitute, TRUE));
2005-03-08 09:25:46 +01:00
2005-03-09 14:10:28 +01:00
g_ptr_array_free(substitutes, TRUE);
2005-03-08 09:25:46 +01:00
2005-03-09 14:10:28 +01:00
team_change_structure(tm, team_find_appropriate_structure(tm));
team_rearrange(tm);
2005-03-08 09:25:46 +01:00
2005-03-18 23:03:23 +01:00
if(team_is_user(tm) == cur_user)
2005-03-09 14:10:28 +01:00
{
2006-06-29 18:06:52 +02:00
game_gui_write_av_skills(NULL);
2005-03-09 14:10:28 +01:00
2005-07-08 11:26:00 +02:00
selected_row = -1;
2005-03-24 21:22:44 +01:00
treeview_show_user_player_list();
2005-03-09 14:10:28 +01:00
}
}
2005-03-09 15:02:49 +01:00
/** Decrease the players' fitness during a live game.
@param fix The match being played. */
void
game_decrease_fitness(const Fixture *fix)
{
#ifdef DEBUG
printf("game_decrease_fitness\n");
#endif
2005-03-09 15:02:49 +01:00
gint i, j;
for(i=0;i<2;i++)
2005-03-10 21:59:39 +01:00
{
2005-10-24 22:50:48 +02:00
if(debug < 50 || team_is_user(fix->teams[i]) == -1)
for(j=0;j<11;j++)
if(player_of_idx_team(fix->teams[i], j)->cskill > 0)
player_decrease_fitness(player_of_idx_team(fix->teams[i], j));
2005-03-10 21:59:39 +01:00
}
}
2005-03-11 13:17:48 +01:00
/** Update the live game stats using the live game unit.
@param live_game_stats Pointer to the live game.
@param live_game_unit The live game unit. */
void
2005-10-20 17:45:00 +02:00
game_update_stats(LiveGame *lg, const LiveGameUnit *unit)
2005-03-11 13:17:48 +01:00
{
#ifdef DEBUG
printf("game_update_stats\n");
#endif
2005-03-11 13:17:48 +01:00
gint i;
2005-10-20 17:45:00 +02:00
LiveGameStats *stats = &lg->stats;
2005-03-11 13:17:48 +01:00
if(unit->minute != -1)
stats->values[unit->possession][LIVE_GAME_STAT_VALUE_POSSESSION]++;
if(unit->event.type == LIVE_GAME_EVENT_SCORING_CHANCE ||
2005-05-13 20:20:47 +02:00
unit->event.type == LIVE_GAME_EVENT_FREE_KICK ||
unit->event.type == LIVE_GAME_EVENT_HEADER)
2005-03-11 13:17:48 +01:00
stats->values[unit->possession][LIVE_GAME_STAT_VALUE_SHOTS]++;
else if(unit->event.type == LIVE_GAME_EVENT_PENALTY)
stats->values[unit->possession][LIVE_GAME_STAT_VALUE_PENALTIES]++;
else if(unit->event.type == LIVE_GAME_EVENT_INJURY)
{
2005-05-19 20:13:14 +02:00
stats->values[unit->event.team][LIVE_GAME_STAT_VALUE_INJURIES]++;
2005-10-20 17:45:00 +02:00
game_update_stats_player(lg, unit);
2005-03-11 13:17:48 +01:00
}
else if(unit->event.type == LIVE_GAME_EVENT_FOUL ||
unit->event.type == LIVE_GAME_EVENT_FOUL_YELLOW ||
unit->event.type == LIVE_GAME_EVENT_FOUL_RED ||
unit->event.type == LIVE_GAME_EVENT_FOUL_RED_INJURY)
{
2005-05-19 20:13:14 +02:00
stats->values[unit->event.team][LIVE_GAME_STAT_VALUE_FOULS]++;
2005-03-11 13:17:48 +01:00
if(unit->event.type == LIVE_GAME_EVENT_FOUL_YELLOW)
{
2005-05-19 20:13:14 +02:00
stats->values[unit->event.team][LIVE_GAME_STAT_VALUE_CARDS]++;
2005-10-20 17:45:00 +02:00
game_update_stats_player(lg, unit);
2005-03-11 13:17:48 +01:00
}
}
else if(unit->event.type == LIVE_GAME_EVENT_SEND_OFF)
{
2005-05-19 20:13:14 +02:00
stats->values[unit->event.team][LIVE_GAME_STAT_VALUE_REDS]++;
2005-10-20 17:45:00 +02:00
game_update_stats_player(lg, unit);
2005-03-11 13:17:48 +01:00
}
2005-04-04 12:36:04 +02:00
else if(unit->event.type == LIVE_GAME_EVENT_GOAL ||
unit->event.type == LIVE_GAME_EVENT_OWN_GOAL)
2005-03-11 13:17:48 +01:00
{
2005-04-04 12:36:04 +02:00
if(live_game_unit_before(unit, -1)->event.type != LIVE_GAME_EVENT_PENALTY &&
unit->event.type != LIVE_GAME_EVENT_OWN_GOAL)
2005-05-19 20:13:14 +02:00
stats->values[unit->event.team][LIVE_GAME_STAT_VALUE_GOALS_REGULAR]++;
2005-10-20 17:45:00 +02:00
game_update_stats_player(lg, unit);
2005-03-11 13:17:48 +01:00
}
2005-04-04 12:36:04 +02:00
2005-03-11 13:17:48 +01:00
for(i=0;i<2;i++)
stats->values[i][LIVE_GAME_STAT_VALUE_SHOT_PERCENTAGE] =
(stats->values[i][LIVE_GAME_STAT_VALUE_SHOTS] > 0) ?
(gint)rint(((gfloat)stats->values[i][LIVE_GAME_STAT_VALUE_GOALS_REGULAR] /
(gfloat)stats->values[i][LIVE_GAME_STAT_VALUE_SHOTS]) * 100) : 0;
}
/** Update the player array in the live game stats.
@param live_game Pointer to the live game.
@param team The team of the player.
@param player The player id.
@param type The type of the stat. */
void
2005-10-20 17:45:00 +02:00
game_update_stats_player(LiveGame *lg, const LiveGameUnit *unit)
2005-03-11 13:17:48 +01:00
{
#ifdef DEBUG
printf("game_update_stats_player\n");
#endif
2005-03-11 13:17:48 +01:00
gint i;
gchar buf[SMALL], buf2[SMALL];
2005-10-20 17:45:00 +02:00
LiveGameStats *stats = &lg->stats;
2005-03-11 13:17:48 +01:00
gint minute = live_game_unit_get_minute(unit), array_index = -1;
gboolean own_goal;
2005-05-19 20:13:14 +02:00
gint team = unit->event.team,
player = unit->event.player,
player2 = unit->event.player2;
2005-10-20 17:45:00 +02:00
const Team *tm[2] = {lg->fix->teams[0],
lg->fix->teams[1]};
2005-03-11 13:17:48 +01:00
GPtrArray *players = NULL;
2008-12-01 21:39:16 +01:00
const gchar *player_name;
2005-03-11 13:17:48 +01:00
if(unit->event.type == LIVE_GAME_EVENT_GOAL ||
unit->event.type == LIVE_GAME_EVENT_OWN_GOAL)
{
own_goal = (unit->event.type == LIVE_GAME_EVENT_OWN_GOAL);
array_index = (own_goal) ? !team : team;
if(live_game_unit_before(unit, -1)->event.type == LIVE_GAME_EVENT_PENALTY)
2005-06-26 13:42:01 +02:00
/* A goal scored with penalty. */
2005-06-18 16:45:29 +02:00
strcpy(buf2, _(" (P)"));
2005-03-11 13:17:48 +01:00
else if(live_game_unit_before(unit, -1)->event.type == LIVE_GAME_EVENT_FREE_KICK)
2005-06-26 13:42:01 +02:00
/* A goal scored with a free kick. */
2005-06-18 16:45:29 +02:00
strcpy(buf2, _(" (FK)"));
2005-03-11 13:17:48 +01:00
else if(unit->event.type == LIVE_GAME_EVENT_OWN_GOAL)
2008-12-01 21:39:16 +01:00
/* An own goal */
2005-06-18 16:45:29 +02:00
strcpy(buf2, _(" (OG)"));
2005-03-11 13:17:48 +01:00
else
strcpy(buf2, "");
2008-12-01 21:39:16 +01:00
player_name = player_of_id_team(tm[team], player)->name;
if(!own_goal)
g_ptr_array_add(stats->players[array_index][LIVE_GAME_STAT_ARRAY_SCORERS], g_strdup(player_name));
for(i=0;i<stats->players[array_index][LIVE_GAME_STAT_ARRAY_SCORERS_FOR_DISPLAY]->len;i++)
2005-03-11 13:17:48 +01:00
{
2005-10-09 11:35:44 +02:00
if(g_str_has_prefix((gchar*)g_ptr_array_index(
2008-12-01 21:39:16 +01:00
stats->players[array_index][LIVE_GAME_STAT_ARRAY_SCORERS_FOR_DISPLAY], i),
player_name))
2005-03-11 13:17:48 +01:00
{
sprintf(buf, "%s %d%s",
2005-10-09 11:35:44 +02:00
(gchar*)g_ptr_array_index(
2008-12-01 21:39:16 +01:00
stats->players[array_index][LIVE_GAME_STAT_ARRAY_SCORERS_FOR_DISPLAY], i),
2005-03-11 13:17:48 +01:00
minute, buf2);
2005-10-09 11:35:44 +02:00
misc_string_assign((gchar**)&g_ptr_array_index(
2008-12-01 21:39:16 +01:00
stats->players[array_index][LIVE_GAME_STAT_ARRAY_SCORERS_FOR_DISPLAY], i), buf);
2005-03-11 13:17:48 +01:00
return;
}
}
2008-12-01 21:39:16 +01:00
sprintf(buf, "%s %d%s", player_name,
2005-03-11 13:17:48 +01:00
minute, buf2);
2008-12-01 21:39:16 +01:00
g_ptr_array_add(stats->players[array_index][LIVE_GAME_STAT_ARRAY_SCORERS_FOR_DISPLAY], g_strdup(buf));
2005-03-11 13:17:48 +01:00
}
else
{
strcpy(buf, "");
if(unit->event.type == LIVE_GAME_EVENT_INJURY)
{
2005-10-09 11:35:44 +02:00
sprintf(buf, "%s", player_of_id_team(tm[team], player)->name);
2005-03-11 13:17:48 +01:00
players = stats->players[team][LIVE_GAME_STAT_ARRAY_INJURED];
}
else if(unit->event.type == LIVE_GAME_EVENT_FOUL_YELLOW)
{
2005-10-09 11:35:44 +02:00
sprintf(buf, "%s", player_of_id_team(tm[team], player2)->name);
2005-03-11 13:17:48 +01:00
players = stats->players[team][LIVE_GAME_STAT_ARRAY_YELLOWS];
}
else if(unit->event.type == LIVE_GAME_EVENT_SEND_OFF)
{
2005-10-09 11:35:44 +02:00
sprintf(buf, "%s", player_of_id_team(tm[team], player)->name);
2005-03-11 13:17:48 +01:00
players = stats->players[team][LIVE_GAME_STAT_ARRAY_REDS];
}
if(strlen(buf) > 0)
2005-10-09 11:35:44 +02:00
g_ptr_array_add(players, strdup(buf));
2005-03-11 13:17:48 +01:00
}
}
2005-03-13 16:46:15 +01:00
/** Make some team updates after a match.
@param fix The match we examine. */
void
game_post_match(Fixture *fix)
{
#ifdef DEBUG
printf("game_post_match\n");
#endif
2005-03-13 16:46:15 +01:00
gint i;
2005-04-24 12:17:20 +02:00
GPtrArray *teams = NULL;
Cup *cup = NULL;
gchar buf[SMALL], buf2[SMALL];
2008-11-28 19:10:01 +01:00
gint usr_idx;
2005-03-13 16:46:15 +01:00
2008-11-28 19:10:01 +01:00
usr_idx = fixture_user_team_involved(fix);
if((debug > 100 && usr_idx != -1) ||
debug > 130)
2005-12-14 15:05:59 +01:00
g_print("game_post_match: %s - %s\n",
fix->teams[0]->name,
fix->teams[1]->name);
2005-03-13 16:46:15 +01:00
if(query_fixture_has_tables(fix))
table_update(fix);
for(i=0;i<2;i++)
team_update_post_match(fix->teams[i], fix);
2008-11-28 19:10:01 +01:00
2005-05-06 18:35:19 +02:00
if(fix->clid < ID_CUP_START)
2005-04-16 09:46:04 +02:00
return;
2005-04-24 12:17:20 +02:00
cup = cup_from_clid(fix->clid);
2005-04-16 09:46:04 +02:00
2005-04-24 12:17:20 +02:00
if(fix->round == cup->rounds->len - 1 &&
fix == &g_array_index(cup->fixtures, Fixture, cup->fixtures->len - 1))
2005-04-16 09:46:04 +02:00
{
2005-04-24 12:17:20 +02:00
teams = cup_get_teams_sorted(cup);
if(team_is_user((Team*)g_ptr_array_index(teams, 0)) != -1)
{
2005-04-24 12:17:20 +02:00
user_history_add(&usr(team_is_user((Team*)g_ptr_array_index(teams, 0))),
USER_HISTORY_WIN_FINAL,
((Team*)g_ptr_array_index(teams, 0))->name,
league_cup_get_name_string(fix->clid),
((Team*)g_ptr_array_index(teams, 1))->name, NULL);
user_add_cup_success(&usr(team_is_user((Team*)g_ptr_array_index(teams, 0))),
cup, fix->round, USER_HISTORY_WIN_FINAL);
}
2005-04-24 12:17:20 +02:00
else if(team_is_user((Team*)g_ptr_array_index(teams, 1)) != -1)
{
2005-04-24 12:17:20 +02:00
user_history_add(&usr(team_is_user((Team*)g_ptr_array_index(teams, 1))),
USER_HISTORY_LOSE_FINAL,
((Team*)g_ptr_array_index(teams, 1))->name,
league_cup_get_name_string(fix->clid),
((Team*)g_ptr_array_index(teams, 0))->name, NULL);
user_add_cup_success(&usr(team_is_user((Team*)g_ptr_array_index(teams, 1))),
cup, fix->round, USER_HISTORY_LOSE_FINAL);
}
2005-04-24 12:17:20 +02:00
g_ptr_array_free(teams, TRUE);
2005-04-16 09:46:04 +02:00
}
2008-11-28 19:10:01 +01:00
else if(usr_idx != -1)
{
cup_get_round_name(cup_from_clid(fix->clid), fix->round, buf);
sprintf(buf2, "%d", fix->round + 1);
2008-11-28 19:10:01 +01:00
user_history_add(&usr(usr_idx),
USER_HISTORY_REACH_CUP_ROUND,
2008-11-28 19:10:01 +01:00
usr(usr_idx).tm->name,
league_cup_get_name_string(fix->clid),
buf, buf2);
2008-11-28 19:10:01 +01:00
user_add_cup_success(&usr(usr_idx),
cup, fix->round, USER_HISTORY_REACH_CUP_ROUND);
}
2005-03-13 16:46:15 +01:00
}
2005-03-16 21:48:25 +01:00
/** Reduce stadium capacity and safety after a stadium event.
@param user The user whose stadium we demolish.
@param type The event type. */
void
game_stadium_event(Stadium *stadium, gint type)
{
#ifdef DEBUG
printf("game_stadium_event\n");
#endif
2005-03-16 21:48:25 +01:00
gfloat reduce;
gfloat reduce_factor[3][2] =
{{const_float("float_game_stadium_safety_reduce_breakdown_lower"),
const_float("float_game_stadium_safety_reduce_breakdown_upper")},
{const_float("float_game_stadium_safety_reduce_riots_lower"),
const_float("float_game_stadium_safety_reduce_riots_upper")},
{const_float("float_game_stadium_safety_reduce_fire_lower"),
const_float("float_game_stadium_safety_reduce_fire_upper")}};
reduce = math_rnd(reduce_factor[type - LIVE_GAME_EVENT_STADIUM_BREAKDOWN][0],
reduce_factor[type - LIVE_GAME_EVENT_STADIUM_BREAKDOWN][1]);
stadium->safety *= (1 - reduce);
stadium->capacity = (gint)rint((gfloat)stadium->capacity *
(1 - reduce *
const_float("float_game_stadium_capacity_reduce_factor")));
}
2005-03-25 11:54:54 +01:00
/** Return the maximum possible values for defence, midfield and attack.
Used in the opponent preview. */
void
2005-09-19 23:13:36 +02:00
game_get_max_values(gfloat max_values[4])
2005-03-25 11:54:54 +01:00
{
#ifdef DEBUG
printf("game_get_max_values\n");
#endif
2005-03-25 11:54:54 +01:00
gint i, j;
Player pl;
pl.skill = pl.cskill = const_float_fast(float_player_max_skill);
2005-03-25 11:54:54 +01:00
pl.fitness = 1;
2005-09-21 10:50:47 +02:00
pl.streak = 0;
2005-03-25 11:54:54 +01:00
max_values[0] = const_float_fast(float_player_max_skill);
2005-09-19 23:13:36 +02:00
for(i=1;i<4;i++)
2005-03-25 11:54:54 +01:00
{
2005-03-25 12:44:49 +01:00
max_values[i] = 0;
2005-03-25 11:54:54 +01:00
for(j=1;j<11;j++)
{
pl.cpos = player_get_position_from_structure(442, j);
max_values[i] += game_get_player_contribution(&pl, i, FALSE);
2005-03-25 11:54:54 +01:00
}
}
}
2005-05-18 18:00:49 +02:00
/** Find out whether there's a default penalty shooter
in the team.
@return A player id or -1. */
gint
game_get_default_penalty_shooter(const Team *tm)
{
#ifdef DEBUG
printf("game_get_default_penalty_shooter\n");
#endif
2005-05-18 18:00:49 +02:00
gint return_value = -1;
if(team_is_user(tm) != -1 &&
option_int("int_opt_user_penalty_shooter",
&usr(team_is_user(tm)).options) != -1 &&
player_of_id_team(tm,
option_int("int_opt_user_penalty_shooter",
&usr(team_is_user(tm)).options)) != NULL &&
player_id_index(tm,
option_int("int_opt_user_penalty_shooter",
&usr(team_is_user(tm)).options), TRUE) < 11 &&
2005-05-18 18:00:49 +02:00
player_of_id_team(tm,
option_int("int_opt_user_penalty_shooter",
&usr(team_is_user(tm)).options))->cskill != 0)
return_value = option_int("int_opt_user_penalty_shooter",
&usr(team_is_user(tm)).options);
return return_value;
}
2005-11-01 22:20:24 +01:00
/** Deduce some money for boost during a match. */
void
game_boost_cost(void)
{
#ifdef DEBUG
printf("game_boost_cost\n");
#endif
2005-11-01 22:20:24 +01:00
gfloat wage_unit = finance_wage_unit(usr(stat2).tm);
gint deduce =
(gint)rint(wage_unit * const_float("float_boost_cost_factor"));
usr(stat2).money -= deduce;
usr(stat2).money_out[1][MON_OUT_BOOST] -= deduce;
}