bygfoot/src/league.c

529 lines
14 KiB
C
Raw Normal View History

2005-03-14 18:47:27 +01:00
#include "cup.h"
2004-12-23 13:58:39 +01:00
#include "league.h"
#include "maths.h"
2005-04-30 09:37:36 +02:00
#include "misc.h"
#include "option.h"
2005-04-13 15:01:59 +02:00
#include "player.h"
2005-04-29 21:48:02 +02:00
#include "stat.h"
2005-04-04 12:36:04 +02:00
#include "table.h"
#include "team.h"
2005-04-29 21:48:02 +02:00
#include "user.h"
#include "variables.h"
2004-12-23 13:58:39 +01:00
/**
Create a new league with some default values.
@return The league we created.
@see League
*/
League
2005-04-14 21:07:25 +02:00
league_new(gboolean new_id)
2004-12-23 13:58:39 +01:00
{
League new;
new.name = g_string_new("");
new.sid = g_string_new("");
2004-12-23 13:58:39 +01:00
new.short_name = g_string_new("");
new.symbol = g_string_new("");
2005-04-14 21:07:25 +02:00
new.id = (new_id) ? league_id_new : -1;
new.average_skill = -1;
new.prom_rel.prom_games_dest_sid = g_string_new("");
2005-04-13 15:01:59 +02:00
new.prom_rel.prom_games_loser_sid = g_string_new("");
new.prom_rel.prom_games_number_of_advance = 1;
2004-12-23 13:58:39 +01:00
new.prom_rel.elements = g_array_new(FALSE, FALSE, sizeof(PromRelElement));
new.teams = g_array_new(FALSE, FALSE, sizeof(Team));
2005-01-09 21:21:22 +01:00
new.fixtures = g_array_new(FALSE, FALSE, sizeof(Fixture));
2004-12-23 13:58:39 +01:00
2005-04-04 12:36:04 +02:00
new.table = table_new();
2005-01-09 21:21:22 +01:00
new.table.clid = new.id;
2004-12-23 13:58:39 +01:00
new.first_week = new.week_gap = 1;
new.yellow_red = 1000;
2005-04-30 15:57:58 +02:00
new.stats = stat_league_new(new.id);
2005-04-29 21:48:02 +02:00
2004-12-23 13:58:39 +01:00
return new;
}
/**
Create a new PromRelElement with default values.
@return The PromRelElement we created.
@see PromRelElement
*/
PromRelElement
prom_rel_element_new(void)
{
PromRelElement new;
new.ranks[0] = new.ranks[1] = 0;
new.dest_sid = g_string_new("");
new.type = PROM_REL_NONE;
2004-12-23 13:58:39 +01:00
return new;
}
2005-01-09 21:21:22 +01:00
/** Get the array index of the given league or cup id.
@param clid The id of the league or cup.
@return The index in the leagues or cups array. */
gint
league_cup_get_index_from_clid(gint clid)
{
gint i;
gint index = -1;
if(clid < ID_CUP_START)
{
for(i=0;i<ligs->len;i++)
if(lig(i).id == clid)
{
index = i;
break;
}
}
else
2005-04-25 21:39:43 +02:00
for(i=0;i<acps->len;i++)
if(acp(i)->id == clid)
2005-01-09 21:21:22 +01:00
{
index = i;
break;
}
if(index == -1)
2005-04-04 12:36:04 +02:00
g_warning("league_cup_get_index_from_clid: couldn't find league or cup with id %d\n", clid);
2005-01-09 21:21:22 +01:00
return index;
}
/** Return the league pointer belonging to the id.
@param clid The id we look for.
@return The league pointer or NULL if failed. */
League*
league_from_clid(gint clid)
{
gint i;
for(i=0;i<ligs->len;i++)
if(lig(i).id == clid)
return &lig(i);
g_warning("league_from_clid: didn't find league with id %d\n", clid);
return NULL;
}
2005-03-14 18:47:27 +01:00
/** Return the id of the next league (or cup if we are
at the end of the leagues array).
@param clid The id of the current league or cup. */
gint
league_cup_get_next_clid(gint clid)
{
gint i, return_value = -1;
if(clid < ID_CUP_START)
{
for(i=0;i<ligs->len;i++)
if(lig(i).id == clid)
break;
if(i != ligs->len - 1)
return_value = lig(i + 1).id;
2005-04-25 21:39:43 +02:00
else if(acps->len > 0)
return_value = acp(0)->id;
2005-03-14 18:47:27 +01:00
else
2005-04-06 13:14:34 +02:00
return_value = lig(0).id;
2005-03-14 18:47:27 +01:00
}
else
{
2005-04-14 21:07:25 +02:00
for(i=0;i<acps->len;i++)
if(acp(i)->id == clid)
2005-04-13 15:01:59 +02:00
break;
2005-03-14 18:47:27 +01:00
2005-04-14 21:07:25 +02:00
if(i != acps->len - 1)
return_value = acp(i + 1)->id;
2005-03-14 18:47:27 +01:00
else
return_value = lig(0).id;
}
return return_value;
}
/** Return the id of the previous league or cup.
@param clid The id of the current league or cup. */
gint
league_cup_get_previous_clid(gint clid)
{
gint i, return_value = -1;
if(clid < ID_CUP_START)
{
for(i=ligs->len - 1;i>=0;i--)
if(lig(i).id == clid)
break;
if(i != 0)
return_value = lig(i - 1).id;
2005-04-14 21:07:25 +02:00
else if(acps->len > 0)
return_value = acp(acps->len - 1)->id;
2005-03-14 18:47:27 +01:00
else
2005-04-06 13:14:34 +02:00
return_value = lig(ligs->len - 1).id;
2005-03-14 18:47:27 +01:00
}
else
{
2005-04-14 21:07:25 +02:00
for(i=acps->len - 1;i>=0;i--)
if(acp(i)->id == clid)
2005-03-14 18:47:27 +01:00
break;
if(i != 0)
2005-04-14 21:07:25 +02:00
return_value = acp(i - 1)->id;
2005-03-14 18:47:27 +01:00
else
return_value = lig(ligs->len - 1).id;
}
return return_value;
}
/** Return the fixture coming after the specified week and round.
@param league The league the fixtures of which we examine.
@return A fixture pointer or NULL. */
Fixture*
league_cup_get_next_fixture(gint clid, gint week_number, gint week_round_number)
{
gint i;
2005-03-27 19:59:57 +02:00
GArray *fixtures = league_cup_get_fixtures(clid);
2005-03-14 18:47:27 +01:00
for(i=0;i<fixtures->len;i++)
if(g_array_index(fixtures, Fixture, i).week_number > week_number ||
(g_array_index(fixtures, Fixture, i).week_number == week_number &&
2005-04-14 21:07:25 +02:00
g_array_index(fixtures, Fixture, i).week_round_number >= week_round_number))
2005-03-14 18:47:27 +01:00
return &g_array_index(fixtures, Fixture, i);
return NULL;
}
/** Return the fixture coming just before the specified week and round.
@param league The league the fixtures of which we examine.
@return A fixture pointer or NULL. */
Fixture*
league_cup_get_previous_fixture(gint clid, gint week_number, gint week_round_number)
{
gint i;
2005-03-27 19:59:57 +02:00
GArray *fixtures = league_cup_get_fixtures(clid);
2005-03-14 18:47:27 +01:00
for(i=fixtures->len - 1;i>=0;i--)
if(g_array_index(fixtures, Fixture, i).week_number < week_number ||
(g_array_index(fixtures, Fixture, i).week_number == week_number &&
g_array_index(fixtures, Fixture, i).week_round_number < week_round_number))
return &g_array_index(fixtures, Fixture, i);
return NULL;
}
/** Return the number of league in the leagues array. */
gint
league_get_index(gint clid)
{
gint i;
for(i=0;i<ligs->len;i++)
if(lig(i).id == clid)
return i;
g_warning("league_get_index: reached end of leagues array; clid is %d\n", clid);
return -1;
}
2005-03-16 21:48:25 +01:00
/** Return the average stadium capacity of cpu teams
in the specified league or cup. */
gint
league_cup_average_capacity(gint clid)
{
gint i;
gfloat sum = 0;
2005-03-27 19:59:57 +02:00
const GArray *teams = league_cup_get_teams(clid);
2005-03-16 21:48:25 +01:00
for(i=0;i<teams->len;i++)
if(team_is_user(&g_array_index(teams, Team, i)) == -1)
sum += g_array_index(teams, Team, i).stadium.capacity;
return sum / (gfloat)teams->len;
}
2005-04-13 15:01:59 +02:00
/** Get the index of the league with the specified string id. */
gint
league_index_from_sid(const gchar *sid)
{
gint i;
for(i=0;i<ligs->len;i++)
if(strcmp(lig(i).sid->str, sid) == 0)
return i;
g_warning("league_index_from_sid: no index found for sid '%s'.\n", sid);
return -1;
}
/** Remove the team with the specified id from the teams
array without freeing the memory (used in promotion/relegation). */
void
league_remove_team_with_id(League *league, gint id)
{
gint i;
for(i=0;i<league->teams->len;i++)
if(g_array_index(league->teams, Team, i).id == id)
{
g_array_remove_index(league->teams, i);
return;
}
g_warning("league_remove_team_with_id: team with id %d in league %s not found\n",
id, league->name->str);
}
/** Add the teams to promote/relegate from the league to the array
and remove them from the leagues. */
void
league_get_team_movements(League *league, GArray *team_movements)
{
2005-04-30 09:37:36 +02:00
gint i, j, k, cp_idx = -1;
2005-04-13 15:01:59 +02:00
gint dest_idx;
gint move_len = team_movements->len;
TeamMove new_move;
const GArray *elements = league->prom_rel.elements;
GPtrArray *prom_games_teams = NULL;
for(i=0;i<elements->len;i++)
{
2005-04-30 09:37:36 +02:00
GPtrArray *dest_sids =
misc_separate_strings(g_array_index(elements, PromRelElement, i).dest_sid->str);
gint order[dest_sids->len];
k = 0;
math_generate_permutation(order, 0, dest_sids->len - 1);
2005-04-13 15:01:59 +02:00
for(j=g_array_index(elements, PromRelElement, i).ranks[0];
j<=g_array_index(elements, PromRelElement, i).ranks[1]; j++)
{
new_move.tm = *(g_array_index(league->table.elements, TableElement, j - 1).team);
2005-04-30 09:37:36 +02:00
new_move.league_idx =
league_index_from_sid(((GString*)g_ptr_array_index(dest_sids, order[k++ % dest_sids->len]))->str);
2005-04-13 15:01:59 +02:00
g_array_append_val(team_movements, new_move);
2005-04-16 09:46:04 +02:00
if(team_is_user(g_array_index(league->table.elements, TableElement, j - 1).team) != -1)
{
if(g_array_index(elements, PromRelElement, i).type == PROM_REL_PROMOTION)
user_history_add(&usr(team_is_user(
g_array_index(league->table.elements, TableElement, j - 1).team)),
USER_HISTORY_PROMOTED, new_move.tm.id, lig(new_move.league_idx).id, -1, "");
else
user_history_add(&usr(team_is_user(
g_array_index(league->table.elements, TableElement, j - 1).team)),
USER_HISTORY_RELEGATED, new_move.tm.id, lig(new_move.league_idx).id, -1, "");
}
2005-04-13 15:01:59 +02:00
}
2005-04-30 09:37:36 +02:00
g_ptr_array_free(dest_sids, TRUE);
2005-04-13 15:01:59 +02:00
}
2005-04-14 21:07:25 +02:00
if(league_has_prom_games(league))
2005-04-13 15:01:59 +02:00
{
2005-04-14 21:07:25 +02:00
for(i=0;i<acps->len;i++)
if(query_cup_is_prom(acp(i)->id))
2005-04-13 15:01:59 +02:00
{
2005-04-14 21:07:25 +02:00
for(j=0;j<acp(i)->fixtures->len;j++)
2005-04-13 15:01:59 +02:00
{
2005-04-14 21:07:25 +02:00
if(g_array_index(acp(i)->fixtures, Fixture, j).teams[0]->clid == league->id ||
g_array_index(acp(i)->fixtures, Fixture, j).teams[1]->clid == league->id)
2005-04-13 15:01:59 +02:00
{
cp_idx = i;
break;
}
}
if(cp_idx != -1)
break;
}
if(cp_idx == -1)
{
g_warning("league_get_team_movements: promotion games cup not found for league %s (dest_sid %s).\n",
league->name->str, league->prom_rel.prom_games_dest_sid->str);
return;
}
2005-04-14 21:07:25 +02:00
prom_games_teams = cup_get_teams_sorted(acp(cp_idx));
2005-04-13 15:01:59 +02:00
dest_idx = league_index_from_sid(league->prom_rel.prom_games_dest_sid->str);
for(i=0;i<league->prom_rel.prom_games_number_of_advance;i++)
{
new_move.tm = *((Team*)g_ptr_array_index(prom_games_teams, i));
new_move.league_idx = dest_idx;
g_array_append_val(team_movements, new_move);
2005-04-16 09:46:04 +02:00
if(team_is_user((Team*)g_ptr_array_index(prom_games_teams, i)) != -1)
user_history_add(&usr(team_is_user(
(Team*)g_ptr_array_index(prom_games_teams, i))),
USER_HISTORY_PROMOTED, new_move.tm.id, lig(dest_idx).id, -1, "");
2005-04-13 15:01:59 +02:00
}
if(strlen(league->prom_rel.prom_games_loser_sid->str) > 0)
{
dest_idx = league_index_from_sid(league->prom_rel.prom_games_loser_sid->str);
for(i=league->prom_rel.prom_games_number_of_advance;i<prom_games_teams->len;i++)
{
new_move.tm = *((Team*)g_ptr_array_index(prom_games_teams, i));
new_move.league_idx = dest_idx;
g_array_append_val(team_movements, new_move);
2005-04-16 09:46:04 +02:00
if(team_is_user((Team*)g_ptr_array_index(prom_games_teams, i)) != -1)
user_history_add(&usr(team_is_user(
(Team*)g_ptr_array_index(prom_games_teams, i))),
USER_HISTORY_RELEGATED, new_move.tm.id, lig(dest_idx).id, -1, "");
2005-04-13 15:01:59 +02:00
}
}
g_ptr_array_free(prom_games_teams, TRUE);
}
for(i=move_len;i<team_movements->len;i++)
league_remove_team_with_id(league_from_clid(g_array_index(team_movements, TeamMove, i).tm.clid),
g_array_index(team_movements, TeamMove, i).tm.id);
}
/** Nullify league stuff at the beginning of a season. */
void
league_season_start(League *league)
{
gint i, j;
gint idx = league_index_from_sid(league->sid->str);
gboolean user_champ =
(team_is_user(
team_of_id(g_array_index(lig(0).table.elements, TableElement, 0).team_id)) != -1);
gfloat team_change_factor = 0;
2005-04-13 15:01:59 +02:00
for(i=0;i<league->table.elements->len;i++)
{
g_array_index(league->table.elements, TableElement, i).team =
&g_array_index(league->teams, Team, i);
g_array_index(league->table.elements, TableElement, i).team_id =
g_array_index(league->teams, Team, i).id;
for(j=0;j<TABLE_END;j++)
g_array_index(league->table.elements, TableElement, i).values[j] = 0;
}
for(i=0;i<league->teams->len;i++)
{
team_change_factor =
(team_is_user(&g_array_index(league->teams, Team, i)) == -1) *
math_rnd(const_float("float_season_end_team_change_lower") +
(user_champ && idx == 0) * const_float("float_season_end_user_champ_addition"),
const_float("float_season_end_team_change_upper") +
(user_champ && idx == 0) * const_float("float_season_end_user_champ_addition"));
2005-04-13 15:01:59 +02:00
for(j=0;j<g_array_index(league->teams, Team, i).players->len;j++)
player_season_start(
&g_array_index(g_array_index(league->teams, Team, i).players, Player, j), team_change_factor);
if(team_is_user(&g_array_index(league->teams, Team, i)) == -1)
team_update_cpu_structure(&g_array_index(league->teams, Team, i));
}
2005-04-13 15:01:59 +02:00
}
/** Find out whether the team with specified rank in the league
would participate in promotion games were the season to end. */
gboolean
query_league_rank_in_prom_games(const League *league, gint rank)
{
gint i, j;
for(i=0;i<ligs->len;i++)
2005-04-14 21:07:25 +02:00
if(league_has_prom_games((&lig(i))))
2005-04-13 15:01:59 +02:00
{
for(j=0;j<lig(i).prom_rel.prom_games_cup.choose_teams->len;j++)
2005-04-14 21:07:25 +02:00
{
2005-04-13 15:01:59 +02:00
if(strcmp(g_array_index(lig(i).prom_rel.prom_games_cup.choose_teams, CupChooseTeam, j).sid->str,
league->sid->str) == 0 &&
2005-04-14 21:07:25 +02:00
((rank >= g_array_index(lig(i).prom_rel.prom_games_cup.choose_teams,
CupChooseTeam, j).start_idx &&
rank <= g_array_index(lig(i).prom_rel.prom_games_cup.choose_teams,
CupChooseTeam, j).end_idx &&
g_array_index(lig(i).prom_rel.prom_games_cup.choose_teams,
CupChooseTeam, j).randomly) ||
(rank >= g_array_index(lig(i).prom_rel.prom_games_cup.choose_teams,
CupChooseTeam, j).start_idx &&
rank < g_array_index(lig(i).prom_rel.prom_games_cup.choose_teams,
CupChooseTeam, j).start_idx +
g_array_index(lig(i).prom_rel.prom_games_cup.choose_teams,
CupChooseTeam, j).number_of_teams &&
!g_array_index(lig(i).prom_rel.prom_games_cup.choose_teams,
CupChooseTeam, j).randomly)))
2005-04-13 15:01:59 +02:00
return TRUE;
2005-04-14 21:07:25 +02:00
}
2005-04-13 15:01:59 +02:00
}
return FALSE;
}
/** Find out whether the promotion games fixtures can be written. */
gboolean
query_league_prom_games_begin(const League *league)
{
gint i, j;
gboolean proceed = FALSE;
for(i=0;i<league->prom_rel.prom_games_cup.choose_teams->len;i++)
{
2005-04-13 15:01:59 +02:00
for(j=0;j<ligs->len;j++)
if(strcmp(lig(j).sid->str,
g_array_index(league->prom_rel.prom_games_cup.choose_teams,
CupChooseTeam, i).sid->str) == 0 &&
g_array_index(lig(j).fixtures, Fixture,
lig(j).fixtures->len - 1).week_number == week &&
g_array_index(lig(j).fixtures, Fixture,
lig(j).fixtures->len - 1).week_round_number == week_round)
proceed = TRUE;
}
if(!proceed)
return FALSE;
for(i=0;i<league->prom_rel.prom_games_cup.choose_teams->len;i++)
{
for(j=0;j<ligs->len;j++)
if(strcmp(lig(j).sid->str,
g_array_index(league->prom_rel.prom_games_cup.choose_teams,
CupChooseTeam, i).sid->str) == 0 &&
g_array_index(lig(j).fixtures, Fixture,
lig(j).fixtures->len - 1).attendance == -1)
return FALSE;
}
return TRUE;
}
2005-04-24 16:19:57 +02:00
/** Find out whether there are/were league matches. */
gboolean
query_league_matches_in_week(const League *league, gint week_number)
{
gint i;
for(i=0;i<league->fixtures->len;i++)
if(g_array_index(league->fixtures, Fixture, i).week_number == week_number)
return TRUE;
return FALSE;
}