#pragma once
#include <cstdarg>
#include <cstdint>
#include <map>
#include <string>
#include <vector>
#include "protocol.hpp"
namespace nethack_mcp
{
/// Translate the pinned NetHack shim into owned observations and input.
class WindowAdapter
{
public:
/// Bind an adapter to the worker's private IPC channel.
WindowAdapter(FramedChannel& channel, std::string game_id);
WindowAdapter(const WindowAdapter&) = delete;
WindowAdapter& operator=(const WindowAdapter&) = delete;
/// Install this adapter as the callback target for NetHack.
void install();
/// Send the native NetHack terminal reason over the worker IPC channel.
static void reportTerminalResult(int how);
private:
struct MenuEntry
{
int entry_id = 0;
std::string text;
bool selectable = false;
bool selected = false;
char letter = 0;
std::vector<unsigned char> identifier;
};
static void callback(const char* name, void* return_ptr,
const char* format, ...);
void handleCallback(const char* name, void* return_ptr,
const char* format, std::va_list arguments);
Json makeSnapshot() const;
Json waitForInput(Json pending);
Json makePending(std::string kind, std::string source) const;
void publishSnapshot(Json snapshot);
void addMessage(const char* message);
void setIntegerReturn(void* return_ptr, int value) const;
void setCharacterReturn(void* return_ptr, char value) const;
void copyTextReturn(void* return_ptr, const std::string& text) const;
int resolveCommand(const std::string& command) const;
FramedChannel& channel_;
std::string game_id_;
std::uint64_t sequence_ = 0;
std::uint64_t input_id_ = 0;
int next_window_id_ = 1;
std::map<int, int> window_types_;
int active_menu_window_ = -1;
int next_menu_entry_id_ = 1;
int cursor_x_ = 1;
int cursor_y_ = 0;
std::vector<std::string> map_rows_;
std::vector<Json> messages_;
bool messages_truncated_ = false;
Json status_ = Json::object();
Json inventory_ = {
{"known", false},
{"stale", true},
{"entries", Json::array()},
};
std::vector<MenuEntry> menu_entries_;
std::string menu_prompt_;
std::string text_window_;
bool inventory_requested_ = false;
std::map<int, std::string> status_fields_;
static WindowAdapter* active_adapter_;
};
} // namespace nethack_mcp