1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.
  2. Guest, due to a lack of interest, playerbase, and general desire to continue, PO will hereby cease our separate tiering and adopt Smogon tiers for SM. More information and updates here.

    Dismiss Notice

How can I make random-playout agent on BattleServer

Discussion in 'Development General' started by 49sunmoon, Jul 2, 2017.

Tags:
  1. 49sunmoon

    49sunmoon New Member

    Joined:
    Jul 2, 2017
    Messages:
    1
    Likes Received:
    0
    # I am beginner at here. If here is not suitable for this kind of talk, please tell me where I go...

    I am thinking of developing pokemon AI.
    As a first step, I am trying to develop random-move agent by modifying source code of BattleServer.

    According to prior research, it will be done by following source code.
    But this article does not contain main.cpp and I wonder how to write it.

    # This is Japanese article, but I paste the code below and if you interested in, I will translate this to English.
    http://shingaryu.hatenablog.com/ent...%e3%82%a4%e3%83%96%e3%83%a9%e3%83%aa%e3%81%a8

    # In these codes, I added English comments

    #ifndef LOCALBATTLETEST_H
    #define LOCALBATTLETEST_H

    #include <QObject>
    #include "battle.h"

    class LocalBattleTest : public QObject
    {
    Q_OBJECT
    public:
    explicit LocalBattleTest(QObject *parent = 0);
    ~LocalBattleTest();
    QHash<int, BattleSituation *> battles;
    ContextSwitcher battleThread;
    BattleServerPluginManager *pluginManager;
    void testBattleExecute();
    void commandChoice(int battleID, BattleChoice choice);
    void ShowCurrentHPs();
    void databaseInit();
    int newBattle(BattlePlayer player1, BattlePlayer player2, ChallengeInfo challengeInfo, TeamBattle team1, TeamBattle team2);
    void ShowCurrentHPs(int battleID);
    signals:

    public slots:
    void notifyInfo(int battleID, int playerID, const QByteArray &info);
    void notifyFinished(int battleid, int result, int winner, int loser);
    };


    #endif // LOCALBATTLETEST_H



    //localbattletest.cpp
    #include "localbattletest.h"
    #include "battle.h"
    #include "pluginmanager.h"
    #include "moves.h"
    #include "abilities.h"
    #include "rbymoves.h"
    #include <PokemonInfo/movesetchecker.h>
    #include "../Shared/battlecommands.h"

    LocalBattleTest::LocalBattleTest(QObject *parent) : QObject(parent)
    {

    databaseInit();
    battleThread.start();
    pluginManager = new BattleServerPluginManager();
    }


    LocalBattleTest::~LocalBattleTest()
    {


    }

    //initialize databese
    void LocalBattleTest::databaseInit()
    {

    //copied from BattleServer::changeDbMod()

    PokemonInfoConfig::setFillMode(FillMode::Server);

    PokemonInfoConfig::changeMod("");

    /* Really useful for headless servers */
    GenInfo::init("db/gens/");
    PokemonInfo::init("db/pokes/");
    MoveSetChecker::init("db/pokes/");
    ItemInfo::init("db/items/");
    MoveInfo::init("db/moves/");
    TypeInfo::init("db/types/");
    NatureInfo::init("db/natures/");
    CategoryInfo::init("db/categories/");
    AbilityInfo::init("db/abilities/");
    HiddenPowerInfo::init("db/types/");
    StatInfo::init("db/status/");
    GenderInfo::init("db/genders/"); //needed by battlelogs plugin

    PokemonInfo::loadStadiumTradebacks();

    MoveEffect::init();
    RBYMoveEffect::init();
    ItemEffect::init();
    AbilityEffect::init();
    }


    void LocalBattleTest::testBattleExecute()
    {

    //set name and ID as you like
    BattlePlayer player1("Satoshi", 0);
    BattlePlayer player2("Shigeru", 1);

    Team team;
    // you can read files made by Generator
    team.loadFromFile("(***file path***)");
    auto team1 = TeamBattle(team);

    auto team2 = TeamBattle();
    team2.generateRandom(Pokemon::gen(Gen::ORAS)); //random party

    newBattle(player1, player2, ChallengeInfo(), team1, team2);
    }


    // create new instance
    int LocalBattleTest::newBattle(BattlePlayer player1, BattlePlayer player2, ChallengeInfo challengeInfo, TeamBattle team1, TeamBattle team2)
    {

    // definition of Qhash to obey the protocol of server

    int initialID = 10; //as you like

    int maxID = 0;
    foreach (auto item, battles.keys()) {
    if(item > maxID){
    maxID = item;
    }
    }
    auto id = battles.count() == 0 ? initialID : maxID + 1;

    // 6 on 6 single battle
    auto newBattle = new BattleSituation(player1, player2, challengeInfo, id, team1, team2, pluginManager);
    battles.insert(id, newBattle);

    //connection between BattleSituation and this object
    connect(newBattle, SIGNAL(battleInfo(int,int,QByteArray)), this, SLOT(notifyInfo(int,int,QByteArray)));
    connect(newBattle, SIGNAL(battleFinished(int,int,int,int)), this, SLOT(notifyFinished(int,int,int,int)));
    newBattle->start(battleThread);

    return id;
    }


    //reaction when receiving signal from BattleSituation
    void LocalBattleTest::notifyInfo(int battleID, int playerID, const QByteArray &info)
    {

    //Decoding information via QbyteArray and DataStream

    DataStream dataStream(info);
    uchar commandNumber;
    qint8 who;
    dataStream >> commandNumber >> who;

    using namespace BattleCommands;

    switch((int)commandNumber) //Only react to OfferChoice
    {
    case BattleCommand::OfferChoice: //OfferChoice means user must send something
    {
    if(who == 0) // showing HP when requirement choice to player1
    {
    ShowCurrentHPs(battleID);
    }

    // List all legal moves and select randomly

    BattleChoices choiceRegulation;
    dataStream >> choiceRegulation;
    QList<BattleChoice> validChoices;
    bool isMegaEvo = choiceRegulation.mega;

    for(int i = 0; i < 4; i++)
    {
    if(choiceRegulation.attackAllowed)
    {
    AttackChoice attack;
    attack.attackTarget = (who == 0) ? 1 : 0;
    attack.attackSlot = i;
    BattleChoice battleChoice(who, attack);
    battleChoice.setMegaEvo(isMegaEvo);

    validChoices << battleChoice;
    }
    }

    if(choiceRegulation.switchAllowed)
    {
    for(int i = 0; i < 6; i++)
    {
    if (!battles[battleID]->isOut(who, i) && !battles[battleID]->poke(who, i).ko())
    {
    SwitchChoice switchChoice;
    switchChoice.pokeSlot = i;
    validChoices << BattleChoice(who, switchChoice);
    }
    }
    }

    commandChoice(battleID, validChoices[rand() % validChoices.length()]);

    break;
    }
    }
    }


    //end of battle
    void LocalBattleTest::notifyFinished(int battleid, int result, int winner, int loser)
    {

    qDebug() << "finished";

    }


    //execute commands
    void LocalBattleTest::commandChoice(int battleID, BattleChoice choice)
    {


    //for debug
    switch(choice.type)
    {
    case ChoiceType::AttackType:
    {
    auto moveNumber = battles[battleID]->poke(choice.slot()).move(choice.attackSlot()).num();
    auto moveName = MoveInfo::Name(moveNumber);
    qDebug() << moveName << "is selected";
    break;
    }
    case ChoiceType::SwitchType:
    {
    auto pokeName = battles[battleID]->poke(choice.slot(), choice.pokeSlot()).nick();
    qDebug() << pokeName << "(change) is selected";
    break;
    }
    }
    qDebug();

    battles[battleID]->battleChoiceReceived(battles[battleID]->id(choice.slot()), choice);
    }


    //show HP for debug
    void LocalBattleTest::ShowCurrentHPs(int battleID)
    {

    auto b = battles[battleID];
    qDebug() << "Player0 HP:" << b->poke(0, 0).lifePoints() << b->poke(0, 1).lifePoints() << b->poke(0, 2).lifePoints() << b->poke(0, 3).lifePoints() << b->poke(0, 4).lifePoints() << b->poke(0, 5).lifePoints();
    qDebug() << "Player1 HP:" << b->poke(1, 0).lifePoints() << b->poke(1, 1).lifePoints() << b->poke(1, 2).lifePoints() << b->poke(1, 3).lifePoints() << b->poke(1, 4).lifePoints() << b->poke(1, 5).lifePoints();
    qDebug();
    }


    I modified main.cpp to

    int main(argc, argv){
    QtCoreApplication a(argc,argv);
    auto lbt = new LocalBattleTest();
    return a.exec();
    }

    I succeed compile. But when I start the binary ./BattleServer, it stops during battle.
    If you know how to fix it please teach me :)