<commit_before>
// ProxyPlayer.hpp
// This will invoke another process and waits for a return code.

#ifndef __PROXY_PLAYER_HPP__
#define __PROXY_PLAYER_HPP__

#include "Player.hpp"
#include <string>
#include <sstream>

#undef UNICODE
#define NOMINMAX
#include <Windows.h>

class ProxyPlayer : public Player
{
public:
	// Initialize with process (without .exe) and identifier of opponent.
	ProxyPlayer(std::string const &process, std::string const &script = "", size_t opponent = -1)
	    : Player(opponent), mProcess(process), mScript(script) {}

public:
	// Invoke other process.
	virtual Action fight()
	{
		unsigned choice = executeWithArguments(getArguments(3));
		switch (choice)
		{
		case 48: return load();
		case 49: return bullet();
		case 50: return plasma();
		case 45: return metal();
		case 61: return thermal();
		default: return (Action)(-1);
		}
	}

	// Notify external program of result.
	virtual void declared(Result result)
	{
		std::string arguments;
		switch (result)
		{
		case WIN:  arguments = getArguments(1);
		case LOSS: arguments = getArguments(2);
		default:   arguments = getArguments(0);
		}
		executeWithArguments(arguments);
	};

private:
	// External process name
	std::string mProcess;

	// External script name (for non binary submissions)
	std::string mScript;

	// Generates argument given game status.
	std::string getArguments(size_t status)
	{
		std::stringstream sst;
		sst << getOpponent()
			<< " " << getTurn()
			<< " " << status
			<< " " << getAmmo()
			<< " " << getAmmoOpponent();
		if (getTurn() > 0)
		{
			sst << " " << toActionString(getHistory())
				<< " " << toActionString(getHistoryOpponent());
		};
		return sst.str();
	}

	// Execute process with given arguments.
	unsigned executeWithArguments(std::string const &arguments) const
	{
		STARTUPINFO startup = { sizeof(startup) };
		PROCESS_INFORMATION process;
		LPSTR lpApplicationName;
		LPSTR lpCommandLine;

		lpApplicationName = const_cast<char *>(mProcess.c_str());
		if (mScript.length() == 0)
		{
			// Binary Proxy Player
			// name.exe arguments
			lpCommandLine = const_cast<char *>(arguments.c_str());
		}
		else
		{
			// Script Proxy Player
			// python.exe script.py arguments
			std::string actualArguments = mScript;
			actualArguments.append(1, ' ');
			actualArguments.append(arguments);
		}

		startup.cb = sizeof(startup);
		BOOL result = CreateProcess(lpApplicationName, lpCommandLine,
			NULL, NULL, TRUE, 0, NULL, NULL, &startup, &process);

		if (!result)
		{
			return -1;
		}
		else
		{
			// Wait for process to terminate and sanitize return code.
			DWORD exitCode;
			WaitForSingleObject(process.hProcess, INFINITE);
			GetExitCodeProcess(process.hProcess, &exitCode);
			return exitCode;
		}
	}
};

// Example: BINARY_PLAYER(CustomPlayer)
// Effects: Invoke CustomPlayer.exe <arguments>
#define BINARY_PLAYER(x)                                              \
	class x final : public ProxyPlayer                                \
	{                                                                 \
	public:                                                           \
		x(size_t opponent = -1) : ProxyPlayer(#x ".exe", opponent) {} \
	};

// Example: SCRIPT_PLAYER(CustomPlayer, "python", "CustomScriptPlayer.py")
// Effects: Invoke python CustomScriptPlayer.py <arguments>
#define SCRIPT_PLAYER(x, y, z)                                        \
	class x final : public ProxyPlayer                                \
	{                                                                 \<commit_msg>Platform-agnostic implementation of ProxyPlayer (using system)<commit_after>
// ProxyPlayer.hpp
// This will invoke another process and waits for a return code.

#ifndef __PROXY_PLAYER_HPP__
#define __PROXY_PLAYER_HPP__

#include "Player.hpp"
#include <string>
#include <sstream>

#ifdef _WIN32
#undef UNICODE
#define NOMINMAX
#include <Windows.h>
#define EXE_SUFFIX ".exe"
#else
#include <cstdlib>
#define EXE_SUFFIX ""
#endif

class ProxyPlayer : public Player
{
public:
	// Initialize with process (without .exe) and identifier of opponent.
	ProxyPlayer(std::string const &process, std::string const &script = "", size_t opponent = -1)
	    : Player(opponent), mProcess(process), mScript(script) {}

public:
	// Invoke other process.
	virtual Action fight()
	{
		unsigned choice = executeWithArguments(getArguments(3));
		switch (choice)
		{
		case 48: return load();
		case 49: return bullet();
		case 50: return plasma();
		case 45: return metal();
		case 61: return thermal();
		default: return (Action)(-1);
		}
	}

	// Notify external program of result.
	virtual void declared(Result result)
	{
		std::string arguments;
		switch (result)
		{
		case WIN:  arguments = getArguments(1);
		case LOSS: arguments = getArguments(2);
		default:   arguments = getArguments(0);
		}
		executeWithArguments(arguments);
	};

private:
	// External process name
	std::string mProcess;

	// External script name (for non binary submissions)
	std::string mScript;

	// Generates argument given game status.
	std::string getArguments(size_t status)
	{
		std::stringstream sst;
		sst << getOpponent()
			<< " " << getTurn()
			<< " " << status
			<< " " << getAmmo()
			<< " " << getAmmoOpponent();
		if (getTurn() > 0)
		{
			sst << " " << toActionString(getHistory())
				<< " " << toActionString(getHistoryOpponent());
		};
		return sst.str();
	}

	// Execute process with given arguments.
	unsigned executeWithArguments(std::string const &arguments) const
	{
#ifdef _WIN32
		STARTUPINFO startup = { sizeof(startup) };
		PROCESS_INFORMATION process;
		LPSTR lpApplicationName;
		LPSTR lpCommandLine;

		lpApplicationName = const_cast<char *>(mProcess.c_str());
		if (mScript.length() == 0)
		{
			// Binary Proxy Player
			// name.exe arguments
			lpCommandLine = const_cast<char *>(arguments.c_str());
		}
		else
		{
			// Script Proxy Player
			// python.exe script.py arguments
			std::string actualArguments = mScript;
			actualArguments.append(1, ' ');
			actualArguments.append(arguments);
		}

		startup.cb = sizeof(startup);
		BOOL result = CreateProcess(lpApplicationName, lpCommandLine,
			NULL, NULL, TRUE, 0, NULL, NULL, &startup, &process);

		if (!result)
		{
			return -1;
		}
		else
		{
			// Wait for process to terminate and sanitize return code.
			DWORD exitCode;
			WaitForSingleObject(process.hProcess, INFINITE);
			GetExitCodeProcess(process.hProcess, &exitCode);
			return exitCode;
		}
#else
		return std::system((mProcess + " " + mScript + " " + arguments).c_str());
#endif
	}
};

// Example: BINARY_PLAYER(CustomPlayer)
// Effects: Invoke CustomPlayer.exe <arguments>
#define BINARY_PLAYER(x)                                              \
	class x final : public ProxyPlayer                                \
	{                                                                 \
	public:                                                           \
	    x(size_t opponent = -1) : ProxyPlayer(#x EXE_SUFFIX, opponent) {} \
	};

// Example: SCRIPT_PLAYER(CustomPlayer, "python", "CustomScriptPlayer.py")
// Effects: Invoke python CustomScriptPlayer.py <arguments>
#define SCRIPT_PLAYER(x, y, z)                                        \
	class x final : public ProxyPlayer                                \
	{                                                                 \
{'fraction_non_alphanumeric': 0.11986348122866894, 'fraction_numerical': 0.006552901023890785, 'mean_word_length': 2.635732009925558, 'pattern_counts': {'":': 0, '<': 70, '<?xml version=': 0, '>': 20, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 18, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1848258', 'n_tokens_mistral': 2462, 'n_tokens_neox': 2182, 'n_words': 570}