1) Applied bugfix for mixing up player karts in AI by SciYann.

2) Added some debug print in case of incorrect kart positions
   (which I have seen once and never again).


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@2164 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2008-07-14 05:21:37 +00:00
parent 0eb36180bd
commit 936f363467
2 changed files with 181 additions and 162 deletions

View File

@ -1,156 +1,157 @@
// $Id$
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2006 SuperTuxKart-Team
//
// 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 3
// of the License, or (at your option) any later version.
//
// 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.
//
// 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef HEADER_RACEMANAGER_H
#define HEADER_RACEMANAGER_H
#include <vector>
#include <algorithm>
#include <string>
#include "cup_data.hpp"
/** The race manager has two functions:
1) it stores information about the race the user selected (e.g. number
of karts, track, race mode etc.)
2) when a race is started, it creates the world, and keeps track of
score during the race. When a race is finished, it deletes the world,
and (depending on race mode) starts the next race by creating a new
world).
Information in the race manager is considered to be more static, sometimes
the world has similar functions showing the current state. E.g.: the
race manager keeps track of the number of karts with which the race was
started, while world keeps track of the number of karts currently in the
race (consider a race mode like follow the leader where karts can get
eliminated).
The race manager handles all race types as a kind of grand prix. E.g.:
a quick race is basically a GP with only one track (so the race manager
keeps track of scores even though no scores are used in a quick race)
**/
class RaceManager
{
public:
enum RaceModeType { RM_TIME_TRIAL, RM_QUICK_RACE, RM_GRAND_PRIX,
RM_FOLLOW_LEADER };
enum Difficulty { RD_EASY, RD_MEDIUM, RD_HARD, RD_SKIDDING };
private:
struct KartStatus
{
std::string m_ident; // The .tkkf filename without the .tkkf
int m_score; // score for this kart
int m_last_score; // needed for restart race
double m_overall_time; // sum of times of all races
double m_last_time; // needed for restart
int m_prev_finish_pos; // previous finished position
int m_player_id; // player controling the kart, for AI: -1
bool m_is_eliminated; // for mini games which can eliminate karts
KartStatus(const std::string& ident, const int& prev_finish_pos,
const int& player_id) :
m_ident(ident), m_score(0), m_last_score(0),
m_overall_time(0.0f), m_last_time(0.0f),
m_prev_finish_pos(prev_finish_pos), m_player_id(player_id),
m_is_eliminated(false)
{}
}; // KartStatus
std::vector<KartStatus> m_kart_status;
Difficulty m_difficulty;
RaceModeType m_race_mode;
typedef std::vector<std::string> PlayerKarts;
PlayerKarts m_player_karts;
std::vector<std::string> m_tracks;
std::vector<int> m_num_laps;
std::vector<int> m_score_for_position;
int m_track_number;
CupData m_cup;
int m_num_karts;
unsigned int m_num_finished_karts;
unsigned int m_num_finished_players;
int m_coin_target;
void startNextRace(); // start a next race
friend bool operator< (const KartStatus& left, const KartStatus& right)
{
return (left.m_score < right.m_score);
}
public:
bool m_active_race; //True if there is a race
public:
RaceManager();
~RaceManager();
void setPlayerKart(unsigned int player, const std::string& kart);
void setNumPlayers(int num);
void reset();
void RaceFinished(const Kart* kart, float time);
void setTrack(const std::string& track);
void setGrandPrix(const CupData &cup){ m_cup = cup; }
void setDifficulty(Difficulty diff);
void setNumLaps(int num) { m_num_laps.clear();
m_num_laps.push_back(num); }
void setRaceMode(RaceModeType mode) { m_race_mode = mode; }
void setNumKarts(int num) { m_num_karts = num; }
void setCoinTarget(int num) { m_coin_target = num; }
RaceModeType getRaceMode() const { return m_race_mode; }
unsigned int getNumKarts() const { return m_num_karts; }
unsigned int getNumPlayers() const { return (int)m_player_karts.size();}
int getNumLaps() const { return m_num_laps[m_track_number];}
Difficulty getDifficulty() const { return m_difficulty; }
const std::string&
getTrackName() const { return m_tracks[m_track_number]; }
const CupData
*getGrandPrix() const { return &m_cup; }
unsigned int getFinishedKarts() const { return m_num_finished_karts; }
unsigned int getFinishedPlayers() const { return m_num_finished_players; }
const std::string&
getKartName(int kart) const { return m_kart_status[kart].m_ident;}
const std::string&
getHerringStyle() const { return m_cup.getHerringStyle(); }
int getKartScore(int krt) const { return m_kart_status[krt].m_score;}
int getPositionScore(int p) const { return m_score_for_position[p-1]; }
double getOverallTime(int kart) const { return m_kart_status[kart].m_overall_time;}
int getCoinTarget() const { return m_coin_target; }
bool isEliminated(int kart) const { return m_kart_status[kart].m_is_eliminated;}
bool raceHasLaps() const { return m_race_mode!=RM_FOLLOW_LEADER;}
void eliminate(int kart) { m_kart_status[kart].m_is_eliminated=true;}
int allPlayerFinished() const {return
m_num_finished_players==m_player_karts.size(); }
int raceIsActive() const { return m_active_race; }
bool isPlayer(int kart) const {return m_kart_status[kart].m_player_id>-1; }
void setMirror() {/*FIXME*/}
void setReverse(){/*FIXME*/}
void startNew(); // start new race/GP/...
void next(); // start the next race or go back to the start screen
void restartRace(); // restart same race again
void exit_race(); // exit a race (and don't start the next one)
};
extern RaceManager *race_manager;
#endif
/* EOF */
// $Id$
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2006 SuperTuxKart-Team
//
// 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 3
// of the License, or (at your option) any later version.
//
// 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.
//
// 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef HEADER_RACEMANAGER_H
#define HEADER_RACEMANAGER_H
#include <vector>
#include <algorithm>
#include <string>
#include "cup_data.hpp"
/** The race manager has two functions:
1) it stores information about the race the user selected (e.g. number
of karts, track, race mode etc.)
2) when a race is started, it creates the world, and keeps track of
score during the race. When a race is finished, it deletes the world,
and (depending on race mode) starts the next race by creating a new
world).
Information in the race manager is considered to be more static, sometimes
the world has similar functions showing the current state. E.g.: the
race manager keeps track of the number of karts with which the race was
started, while world keeps track of the number of karts currently in the
race (consider a race mode like follow the leader where karts can get
eliminated).
The race manager handles all race types as a kind of grand prix. E.g.:
a quick race is basically a GP with only one track (so the race manager
keeps track of scores even though no scores are used in a quick race)
**/
class RaceManager
{
public:
enum RaceModeType { RM_TIME_TRIAL, RM_QUICK_RACE, RM_GRAND_PRIX,
RM_FOLLOW_LEADER };
enum Difficulty { RD_EASY, RD_MEDIUM, RD_HARD, RD_SKIDDING };
private:
struct KartStatus
{
std::string m_ident; // The .tkkf filename without the .tkkf
int m_score; // score for this kart
int m_last_score; // needed for restart race
double m_overall_time; // sum of times of all races
double m_last_time; // needed for restart
int m_prev_finish_pos; // previous finished position
int m_player_id; // player controling the kart, for AI: -1
bool m_is_eliminated; // for mini games which can eliminate karts
KartStatus(const std::string& ident, const int& prev_finish_pos,
const int& player_id) :
m_ident(ident), m_score(0), m_last_score(0),
m_overall_time(0.0f), m_last_time(0.0f),
m_prev_finish_pos(prev_finish_pos), m_player_id(player_id),
m_is_eliminated(false)
{}
}; // KartStatus
std::vector<KartStatus> m_kart_status;
Difficulty m_difficulty;
RaceModeType m_race_mode;
typedef std::vector<std::string> PlayerKarts;
PlayerKarts m_player_karts;
std::vector<std::string> m_tracks;
std::vector<int> m_num_laps;
std::vector<int> m_score_for_position;
int m_track_number;
CupData m_cup;
int m_num_karts;
unsigned int m_num_finished_karts;
unsigned int m_num_finished_players;
int m_coin_target;
void startNextRace(); // start a next race
friend bool operator< (const KartStatus& left, const KartStatus& right)
{
return (left.m_score < right.m_score);
}
public:
bool m_active_race; //True if there is a race
public:
RaceManager();
~RaceManager();
void setPlayerKart(unsigned int player, const std::string& kart);
void setNumPlayers(int num);
void reset();
void RaceFinished(const Kart* kart, float time);
void setTrack(const std::string& track);
void setGrandPrix(const CupData &cup){ m_cup = cup; }
void setDifficulty(Difficulty diff);
void setNumLaps(int num) { m_num_laps.clear();
m_num_laps.push_back(num); }
void setRaceMode(RaceModeType mode) { m_race_mode = mode; }
void setNumKarts(int num) { m_num_karts = num; }
void setCoinTarget(int num) { m_coin_target = num; }
RaceModeType getRaceMode() const { return m_race_mode; }
unsigned int getNumKarts() const { return m_num_karts; }
unsigned int getNumPlayers() const { return (int)m_player_karts.size();}
int getNumLaps() const { return m_num_laps[m_track_number];}
Difficulty getDifficulty() const { return m_difficulty; }
const std::string&
getTrackName() const { return m_tracks[m_track_number]; }
const CupData
*getGrandPrix() const { return &m_cup; }
unsigned int getFinishedKarts() const { return m_num_finished_karts; }
unsigned int getFinishedPlayers() const { return m_num_finished_players; }
const std::string&
getKartName(int kart) const { return m_kart_status[kart].m_ident;}
const std::string&
getHerringStyle() const { return m_cup.getHerringStyle(); }
int getKartScore(int krt) const { return m_kart_status[krt].m_score;}
int getkartPlayerId(int krt) const { return m_kart_status[krt].m_player_id;}
int getPositionScore(int p) const { return m_score_for_position[p-1]; }
double getOverallTime(int kart) const { return m_kart_status[kart].m_overall_time;}
int getCoinTarget() const { return m_coin_target; }
bool isEliminated(int kart) const { return m_kart_status[kart].m_is_eliminated;}
bool raceHasLaps() const { return m_race_mode!=RM_FOLLOW_LEADER;}
void eliminate(int kart) { m_kart_status[kart].m_is_eliminated=true;}
int allPlayerFinished() const {return
m_num_finished_players==m_player_karts.size(); }
int raceIsActive() const { return m_active_race; }
bool isPlayer(int kart) const {return m_kart_status[kart].m_player_id>-1; }
void setMirror() {/*FIXME*/}
void setReverse(){/*FIXME*/}
void startNew(); // start new race/GP/...
void next(); // start the next race or go back to the start screen
void restartRace(); // restart same race again
void exit_race(); // exit a race (and don't start the next one)
};
extern RaceManager *race_manager;
#endif
/* EOF */

View File

@ -95,13 +95,15 @@ World::World()
// karts can be positioned properly on (and not in) the tracks.
loadTrack() ;
int playerIndex = 0;
m_player_karts.resize(race_manager->getNumPlayers());
for(unsigned int i=0; i<race_manager->getNumKarts(); i++)
{
int position = i+1; // position start with 1
btTransform init_pos=m_track->getStartTransform(position);
Kart* newkart;
const std::string& kart_name=race_manager->getKartName(i);
int player_id = race_manager->getkartPlayerId(i);
if(user_config->m_profile)
{
// In profile mode, load only the old kart
@ -110,7 +112,7 @@ World::World()
// karts can be seen.
if(i==race_manager->getNumKarts()-1)
{
scene->createCamera(playerIndex, newkart);
scene->createCamera(player_id, newkart);
}
}
else
@ -118,10 +120,9 @@ World::World()
if (race_manager->isPlayer(i))
{
newkart = new PlayerKart(kart_name, position,
&(user_config->m_player[playerIndex]),
init_pos, playerIndex);
m_player_karts.push_back((PlayerKart*)newkart);
playerIndex++;
&(user_config->m_player[player_id]),
init_pos, player_id);
m_player_karts[player_id] = (PlayerKart*)newkart;
}
else
{
@ -322,6 +323,10 @@ void World::updateHighscores()
// again by a faster kart in the same race), which might be confusing
// if we ever decide to display a message (e.g. during a race)
unsigned int *index = new unsigned int[m_kart.size()];
#ifdef DEBUG
// FIXME begin: for debugging only: had a bug here once, couldn't reproduce it:
for(unsigned int i=0; i<m_kart.size(); i++) index[i]=-1;
#endif
for (unsigned int i=0; i<m_kart.size(); i++ )
{
index[m_kart[i]->getPosition()-1] = i;
@ -329,6 +334,19 @@ void World::updateHighscores()
for(unsigned int pos=0; pos<m_kart.size(); pos++)
{
#ifdef DEBUG
// FIXME begin: triggered if the positions of the karts are incorrect:
if(index[pos]<0)
{
fprintf(stderr, "Error, incorrect kart positions:");
for (unsigned int i=0; i<m_kart.size(); i++ )
{
fprintf(stderr, "i=%d position %d\n",i, m_kart[i]->getPosition());
}
}
#endif
// FIXME: end
// Only record times for player karts
if(!m_kart[index[pos]]->isPlayerKart()) continue;