Changeset 24962

Timestamp:
Feb 28, 2021, 1:16:32 PM (3 years ago)
Author:
wraitii
Message:

Add an 'Evaluate' RL endpoint, intended for dynamic game balancing

This adds a new endpoint to the RL interface for evaluating custom JavaScript. When combined with the ability to create arbitrary modifiers, this provides the required functionality for exploring quantitative game balancing.

Patch By: irishninja

Fixes #5981

Differential Revision: https://code.wildfiregames.com/D3479

Location:
ps/trunk/source
Files:
2 added
5 edited

Legend:

Unmodified
Added
Removed
  • ps/trunk/source/rlinterface/RLInterface.cpp

    r24844 r24962  
    6363    m_GameMessage = std::move(msg);
    6464    m_MsgApplied.wait(msgLock, [this]() { return m_GameMessage.type == GameMessageType::None; });
    65     return m_GameState;
     65    return m_e;
    6666}
    6767
     
    7777    m_ScenarioConfig = std::move(scenario);
    7878    return SendGameMessage({ GameMessageType::Reset });
     79
     80
     81
     82
     83
     84
     85
    7986}
    8087
     
    193200                stream << gameState.c_str();
    194201        }
     202
     203
     204
     205
     206
     207
     208
     209
     210
     211
     212
     213
     214
     215
     216
     217
     218
     219
     220
     221
     222
     223
     224
     225
    195226        else if (uri == "/templates")
    196227        {
     
    275306    if (m_NeedsGameState && isGameStarted)
    276307    {
    277         m_GameState = GetGameState();
     308        m_e = GetGameState();
    278309        m_MsgApplied.notify_one();
    279310        m_MsgLock.unlock();
     
    319350                LDR_NonprogressiveLoad();
    320351                ENSURE(g_Game->ReallyStartGame() == PSRETURN_OK);
    321                 m_GameState = GetGameState();
     352                m_e = GetGameState();
    322353                m_MsgApplied.notify_one();
    323354                m_MsgLock.unlock();
     
    343374            if (!g_Game)
    344375            {
    345                 m_GameState = EMPTY_STATE;
     376                m_e = EMPTY_STATE;
    346377                m_MsgApplied.notify_one();
    347378                m_MsgLock.unlock();
     
    369400                g_Game->Update(deltaRealTime);
    370401
    371             m_GameState = GetGameState();
     402            m_e = GetGameState();
    372403            m_MsgApplied.notify_one();
    373404            m_MsgLock.unlock();
    374405            break;
    375406        }
     407
     408
     409
     410
     411
     412
     413
     414
     415
     416
     417
     418
     419
     420
     421
     422
     423
     424
    376425        default:
    377426        break;
  • ps/trunk/source/rlinterface/RLInterface.h

    r24839 r24962  
    1 /* Copyright (C) 2020 Wildfire Games.
     1/* Copyright (C) 202 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
     
    4646    Reset,
    4747    Commands,
     48
    4849};
    4950
     
    7273 *  0. The game/main thread calls TryApplyMessage()
    7374 *    - If no messages are pending, GOTO 0 (the simulation is not advanced).
    74  *  1. TryApplyMessage locks m_MsgLock, pulls the message, processes it, advances the simulation, and sets m_GameState.
     75 *  1. TryApplyMessage locks m_MsgLock, pulls the message, processes it, advances the simulation, and sets m_e.
    7576 *  2. TryApplyMessage notifies the RL thread that it can carry on and unlocks m_MsgLock. The main thread carries on frame rendering and goes back to 0.
    76  *  3. The RL thread locks m_MsgLock, reads m_GameState, unlocks m_MsgLock, and sends the gamestate as HTTP Response to the RL client.
     77 *  3. The RL thread locks m_MsgLock, reads m_e, unlocks m_MsgLock, and sends the gamestate as HTTP Response to the RL client.
    7778 *  4. The client processes the response and ultimately sends a new HTTP message to the RL Interface.
    7879 *  5. The RL thread locks m_MsgLock, pushes the message, and starts waiting on the game/main thread to notify it (step 2).
     
    8788    /**
    8889     * Non-blocking call to process any pending messages from the RL client.
    89      * Updates m_GameState to the gamestate after messages have been processed.
     90     * Updates m_e to the gamestate after messages have been processed.
    9091     */
    9192    void TryApplyMessage();
     
    106107     */
    107108    std::string Reset(ScenarioConfig&& scenario);
     109
     110
     111
     112
     113
     114
    108115
    109116    /**
     
    132139    /**
    133140     * Process any pending messages from the RL client.
    134      * Updates m_GameState to the gamestate after messages have been processed.
     141     * Updates m_e to the gamestate after messages have been processed.
    135142     */
    136143    void ApplyMessage(const GameMessage& msg);
     
    145152    GameMessage m_GameMessage;
    146153    ScenarioConfig m_ScenarioConfig;
    147     std::string m_GameState;
     154    std::string m_e;
    148155    bool m_NeedsGameState = false;
    149156
     
    151158    std::mutex m_MsgLock;
    152159    std::condition_variable m_MsgApplied;
     160
    153161};
    154162
  • ps/trunk/source/tools/rlclient/python/tests/test_actions.py

    r24816 r24962  
    7979def test_attack():
    8080    state = game.reset(config)
    81     units = state.units(owner=1, type='cavalry')
     81    unit
    8282    target = state.units(owner=2, type='female_citizen')[0]
    83     initial_health = target.health()
     83    initial_health_target = target.health()
     84    initial_health_unit = unit.health()
    8485
    8586    state = game.step([zero_ad.actions.reveal_map()])
    8687
    87     attack = zero_ad.actions.attack(units, target)
     88    attack = zero_ad.actions.attack(, target)
    8889    state = game.step([attack])
    89     while state.unit(target.id()).health() >= initial_health:
     90    while (state.unit(target.id()).health() >= initial_health_target
     91        ) and (state.unit(unit.id()).health() >= initial_health_unit):
    9092        state = game.step()
    9193
  • ps/trunk/source/tools/rlclient/python/zero_ad/api.py

    r23917 r24962  
    2828        response = self.post('templates', post_data)
    2929        return zip(names, response.decode().split('\n'))
     30
     31
     32
     33
  • ps/trunk/source/tools/rlclient/python/zero_ad/environment.py

    r23917 r24962  
    2525        self.current_state = GameState(json.loads(state_json), self)
    2626        return self.current_state
     27
     28
     29
    2730
    2831    def get_template(self, name):
Note: See TracChangeset for help on using the changeset viewer.