Add network ai tester for linear race

This commit is contained in:
Benau 2018-09-16 17:58:00 +08:00
parent 2c35b0f03c
commit b3bffacb40
11 changed files with 233 additions and 17 deletions

View File

@ -48,6 +48,7 @@ AIBaseController::AIBaseController(AbstractKart *kart)
void AIBaseController::reset()
{
m_enabled_network_ai = false;
m_stuck = false;
m_collision_ticks.clear();
} // reset

View File

@ -43,6 +43,7 @@ private:
bool m_stuck;
protected:
bool m_enabled_network_ai;
/** Length of the kart, storing it here saves many function calls. */
float m_kart_length;
@ -106,6 +107,7 @@ public:
// ------------------------------------------------------------------------
virtual void saveState(BareNetworkString *buffer) const OVERRIDE;
virtual void rewindTo(BareNetworkString *buffer) OVERRIDE;
void setNetworkAI(bool val) { m_enabled_network_ai = val; }
}; // AIBaseController

View File

@ -103,6 +103,8 @@ public:
/** Get a pointer on the kart controls. */
virtual KartControl* getControls() { return m_controls; }
// ------------------------------------------------------------------------
void setControls(KartControl* kc) { m_controls = kc; }
// ------------------------------------------------------------------------
/** Only local players can get achievements. */
virtual bool canGetAchievements () const { return false; }
// ------------------------------------------------------------------------

View File

@ -0,0 +1,122 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2018 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.
#include "karts/controller/network_ai_controller.hpp"
#include "graphics/camera.hpp"
#include "karts/abstract_kart.hpp"
#include "karts/controller/kart_control.hpp"
#include "karts/controller/skidding_ai.hpp"
#include "modes/world.hpp"
#include "network/protocols/game_protocol.hpp"
#include "network/network_config.hpp"
#include "network/rewind_manager.hpp"
// ============================================================================
const int UPDATE_FREQUENCY = 30;
// ----------------------------------------------------------------------------
NetworkAIController::NetworkAIController(AbstractKart *kart,
int local_player_id,
SkiddingAI* ai)
: PlayerController(kart)
{
m_ai_controller = ai;
m_ai_controls = new KartControl;
Camera::createCamera(kart, local_player_id);
ai->setControls(m_ai_controls);
} // NetworkAIController
// ----------------------------------------------------------------------------
NetworkAIController::~NetworkAIController()
{
delete m_ai_controls;
} // ~NetworkAIController
// ----------------------------------------------------------------------------
void NetworkAIController::update(int ticks)
{
if (!RewindManager::get()->isRewinding())
{
if (World::getWorld()->isStartPhase() ||
World::getWorld()->getTicksSinceStart() > m_prev_update_ticks)
{
m_prev_update_ticks = World::getWorld()->getTicksSinceStart() +
UPDATE_FREQUENCY;
m_ai_controller->update(UPDATE_FREQUENCY);
convertAIToPlayerActions();
}
}
PlayerController::update(ticks);
} // update
// ----------------------------------------------------------------------------
void NetworkAIController::reset()
{
m_prev_update_ticks = 0;
m_ai_controller->reset();
m_ai_controller->setNetworkAI(true);
m_ai_controls->reset();
PlayerController::reset();
} // reset
// ----------------------------------------------------------------------------
void NetworkAIController::convertAIToPlayerActions()
{
std::vector<std::pair<PlayerAction, int> > all_actions;
if (m_ai_controls->getSteer() < 0.0f)
{
all_actions.emplace_back(PA_STEER_LEFT,
fabsf(m_ai_controls->getSteer()) * 32768);
}
else
{
all_actions.emplace_back(PA_STEER_RIGHT,
fabsf(m_ai_controls->getSteer()) * 32768);
}
all_actions.emplace_back(PA_ACCEL,
m_ai_controls->getAccel() * 32768);
all_actions.emplace_back(PA_BRAKE,
m_ai_controls->getBrake() ? 32768 : 0);
all_actions.emplace_back(PA_FIRE,
m_ai_controls->getFire() ? 32768 : 0);
all_actions.emplace_back(PA_NITRO,
m_ai_controls->getNitro() ? 32768 : 0);
all_actions.emplace_back(PA_DRIFT,
m_ai_controls->getSkidControl() == KartControl::SC_NONE ?
0 : 32768);
all_actions.emplace_back(PA_RESCUE,
m_ai_controls->getRescue() ? 32768 : 0);
for (const auto& a : all_actions)
{
if (!PlayerController::action(a.first, a.second, /*dry_run*/true))
continue;
if (NetworkConfig::get()->isNetworking() &&
NetworkConfig::get()->isClient() &&
!RewindManager::get()->isRewinding())
{
if (auto gp = GameProtocol::lock())
{
gp->controllerAction(m_kart->getWorldKartId(),
a.first, a.second,
m_steer_val_l, m_steer_val_r);
}
}
PlayerController::action(a.first, a.second, false);
}
} // convertAIToPlayerActions

View File

@ -0,0 +1,42 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2018 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_NETWORK_AI_CONTROLLER_HPP
#define HEADER_NETWORK_AI_CONTROLLER_HPP
#include "karts/controller/player_controller.hpp"
class AbstractKart;
class SkiddingAI;
class NetworkAIController : public PlayerController
{
private:
int m_prev_update_ticks;
SkiddingAI* m_ai_controller;
KartControl* m_ai_controls;
void convertAIToPlayerActions();
public:
NetworkAIController(AbstractKart *kart, int local_player_id,
SkiddingAI* ai);
virtual ~NetworkAIController();
virtual void update(int ticks) OVERRIDE;
virtual void reset() OVERRIDE;
}; // class NetworkAIController
#endif // HEADER_PLAYER_CONTROLLER_HPP

View File

@ -221,6 +221,8 @@ unsigned int SkiddingAI::getNextSector(unsigned int index)
void SkiddingAI::update(int ticks)
{
float dt = stk_config->ticks2Time(ticks);
m_controls->setRescue(false);
// This is used to enable firing an item backwards.
m_controls->setLookBack(false);
m_controls->setNitro(false);
@ -293,6 +295,10 @@ void SkiddingAI::update(int ticks)
// If the kart needs to be rescued, do it now (and nothing else)
if(isStuck() && !m_kart->getKartAnimation())
{
// For network AI controller
if (m_enabled_network_ai)
m_controls->setRescue(true);
else
new RescueAnimation(m_kart);
AIBaseLapController::update(ticks);
return;
@ -2085,6 +2091,11 @@ void SkiddingAI::handleRaceStart()
{
if( m_start_delay < 0 )
{
if (m_enabled_network_ai)
{
m_start_delay = 0;
return;
}
// Each kart starts at a different, random time, and the time is
// smaller depending on the difficulty.
m_start_delay = stk_config->time2Ticks(
@ -2122,6 +2133,10 @@ void SkiddingAI::handleRescue(const float dt)
m_time_since_stuck += dt;
if(m_time_since_stuck > 2.0f)
{
// For network AI controller
if (m_enabled_network_ai)
m_controls->setRescue(true);
else
new RescueAnimation(m_kart);
m_time_since_stuck=0.0f;
} // m_time_since_stuck > 2.0f

View File

@ -610,6 +610,8 @@ void cmdLineHelp()
" (in format x.x.x.x:xxx(port)), the port should be its\n"
" public port.\n"
" --server-id=n Server id in stk addons for --connect-now.\n"
" --network-ai=n Numbers of AI for connecting to linear race server, used\n"
" together with --connect-now.\n"
" --login=s Automatically log in (set the login).\n"
" --password=s Automatically log in (set the password).\n"
" --init-user Save the above login and password (if set) in config.\n"
@ -1272,14 +1274,28 @@ int handleCmdLine(bool has_server_config, bool has_parent_process)
if (CommandLine::has("--connect-now", &s))
{
TransportAddress server_addr(s);
NetworkConfig::get()->setIsWAN();
NetworkConfig::get()->setIsServer(false);
auto server = std::make_shared<Server>(0, L"", 0, 0, 0, 0, server_addr,
!server_password.empty(), false);
if (CommandLine::has("--network-ai", &n))
{
NetworkConfig::get()->setNetworkAITester(true);
PlayerManager::get()->createGuestPlayers(n);
for (int i = 0; i < n; i++)
{
NetworkConfig::get()->addNetworkPlayer(
NULL, PlayerManager::get()->getPlayer(i),
PLAYER_DIFFICULTY_NORMAL);
}
}
else
{
NetworkConfig::get()->addNetworkPlayer(
input_manager->getDeviceManager()->getLatestUsedDevice(),
PlayerManager::getCurrentPlayer(), PLAYER_DIFFICULTY_NORMAL);
}
TransportAddress server_addr(s);
auto server = std::make_shared<Server>(0, L"", 0, 0, 0, 0, server_addr,
!server_password.empty(), false);
NetworkConfig::get()->doneAddingNetworkPlayers();
STKHost::create();
auto cts = std::make_shared<ConnectToServer>(server);

View File

@ -44,6 +44,7 @@
#include "karts/controller/soccer_ai.hpp"
#include "karts/controller/spare_tire_ai.hpp"
#include "karts/controller/test_ai.hpp"
#include "karts/controller/network_ai_controller.hpp"
#include "karts/controller/network_player_controller.hpp"
#include "karts/kart.hpp"
#include "karts/kart_model.hpp"
@ -387,15 +388,22 @@ std::shared_ptr<AbstractKart> World::createKart
{
case RaceManager::KT_PLAYER:
{
controller = new LocalPlayerController(new_kart.get(), local_player_id,
difficulty);
if (NetworkConfig::get()->isNetworkAITester())
{
controller = new NetworkAIController(new_kart.get(),
local_player_id, new SkiddingAI(new_kart.get()));
}
else
{
controller = new LocalPlayerController(new_kart.get(),
local_player_id, difficulty);
const PlayerProfile* p = StateManager::get()
->getActivePlayer(local_player_id)->getConstProfile();
if (p && p->getDefaultKartColor() > 0.0f)
{
ri->setHue(p->getDefaultKartColor());
}
}
m_num_players ++;
break;
}

View File

@ -54,6 +54,7 @@ NetworkConfig::NetworkConfig()
m_client_port = UserConfigParams::m_random_client_port ?
0 : stk_config->m_client_port;
m_joined_server_version = 0;
m_network_ai_tester = false;
} // NetworkConfig
// ----------------------------------------------------------------------------

View File

@ -65,14 +65,17 @@ private:
/** True if this host is a server, false otherwise. */
bool m_is_server;
/** The LAN port on which a client is waiting for a server connection. */
uint16_t m_client_port;
/** True if a client should connect to the first server it finds and
* immediately start a race. */
bool m_auto_connect;
bool m_done_adding_network_players;
bool m_network_ai_tester;
/** The LAN port on which a client is waiting for a server connection. */
uint16_t m_client_port;
/** Used by wan server. */
uint32_t m_cur_user_id;
std::string m_cur_user_token;
@ -154,7 +157,7 @@ public:
{
for (auto& p : m_network_players)
{
if (std::get<0>(p) == device)
if (std::get<0>(p) == device && !m_network_ai_tester)
return false;
if (std::get<1>(p) == profile)
return false;
@ -192,6 +195,10 @@ public:
* requested. */
bool isAutoConnect() const { return m_auto_connect; }
// ------------------------------------------------------------------------
void setNetworkAITester(bool b) { m_network_ai_tester = b; }
// ------------------------------------------------------------------------
bool isNetworkAITester() const { return m_network_ai_tester; }
// ------------------------------------------------------------------------
void setCurrentUserId(uint32_t id) { m_cur_user_id = id ; }
// ------------------------------------------------------------------------
void setCurrentUserToken(const std::string& t) { m_cur_user_token = t; }