Set up a basic ttrts binary
It takes a game description from the command line. Looks in a folder 'ttrts_gamename' for turn commands Reads those in and simulates until a winner is found
This commit is contained in:
parent
a90ad9f90c
commit
2a410d98c0
4 changed files with 184 additions and 3 deletions
|
@ -342,6 +342,25 @@ CUnit& CTTRTSGame::GetUnitByID( unit_id_t id )
|
|||
return invalid_unit;
|
||||
}
|
||||
|
||||
// Get a vector of the teams in the current game
|
||||
std::vector<Team> CTTRTSGame::GetTeams() const
|
||||
{
|
||||
std::vector<Team> teams;
|
||||
teams.reserve(GetNumUnits());
|
||||
|
||||
// Grab all teams
|
||||
for ( const OrderUnitPair& pair : m_OrderUnitPairs )
|
||||
{
|
||||
teams.push_back(pair.unit.getTeam());
|
||||
}
|
||||
|
||||
// Remove dupes
|
||||
std::sort( teams.begin(), teams.end() );
|
||||
teams.erase( std::unique( teams.begin(), teams.end() ), teams.end() );
|
||||
|
||||
return teams;
|
||||
}
|
||||
|
||||
// Check if we have a win state
|
||||
Team CTTRTSGame::CheckForWin() const
|
||||
{
|
||||
|
|
|
@ -96,6 +96,10 @@ public:
|
|||
|
||||
// Set the turn of the game
|
||||
inline int SetTurn( int in ) { return (turn = in); }
|
||||
inline int GetTurn() const { return turn; }
|
||||
|
||||
// Get a vector of the teams in the current game
|
||||
std::vector<Team> GetTeams() const;
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
# Project name
|
||||
project( ttrts )
|
||||
|
||||
include_directories(
|
||||
../maths
|
||||
../game
|
||||
)
|
||||
|
||||
# Add the sources
|
||||
set( SOURCES
|
||||
main.cpp
|
||||
|
@ -9,3 +14,5 @@ set( SOURCES
|
|||
|
||||
# Add the executable
|
||||
add_executable( ttrts ${SOURCES} )
|
||||
|
||||
target_link_libraries( ttrts game )
|
|
@ -1,5 +1,156 @@
|
|||
// Main program entry point
|
||||
int main()
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "game.h"
|
||||
|
||||
static const char* sk_usage = "NAME\n"
|
||||
"\tttrts - Tiny Terminal RTS\n"
|
||||
"\n"
|
||||
"SYNOPSYS\n"
|
||||
"\tttrts [OPTIONS...] infile\n"
|
||||
"\n"
|
||||
"DESCRIPTION\n"
|
||||
"\tWhen invoked, ttrts will set up a full game and output a single file representing\n"
|
||||
"\tthe current game state.\n"
|
||||
"\tThis file can be read in and interpretted by human, robot, or cat.\n"
|
||||
"\tttrts will wait for orders files to be placed in it's current working directory.\n"
|
||||
"\tOnce orders have been set for each player taking part, ttrts consumes order files,\n"
|
||||
"\tcalculates new game state and outputs a new file.\n"
|
||||
"\n"
|
||||
"\tThis process repeats until a winner is chosen!\n";
|
||||
|
||||
// time for waiting between file stats
|
||||
static const std::chrono::milliseconds sk_waitTime = std::chrono::milliseconds(100);
|
||||
|
||||
// Check if a file exists
|
||||
inline bool FileExists( const std::string& name )
|
||||
{
|
||||
struct stat buffer;
|
||||
return (stat (name.c_str(), &buffer) == 0);
|
||||
}
|
||||
|
||||
// Wait for a file to exist
|
||||
inline void WaitForFile( const std::string& name, const std::chrono::milliseconds& time )
|
||||
{
|
||||
while( !FileExists(name) ) std::this_thread::sleep_for(time);
|
||||
}
|
||||
|
||||
// Main program entry point
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
// If no args, print usage
|
||||
if ( argc == 1 )
|
||||
{
|
||||
std::cerr<<sk_usage<<std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Attempt to open the game file
|
||||
std::string gameFile = argv[1];
|
||||
std::ifstream file(gameFile);
|
||||
|
||||
if( file.bad() )
|
||||
{
|
||||
std::cerr<<"Error: "<<gameFile<<" file not found"<<std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string gameDescriptor;
|
||||
|
||||
// Reserve the string needed up front
|
||||
file.seekg(0, std::ios::end);
|
||||
gameDescriptor.reserve(file.tellg());
|
||||
file.seekg(0, std::ios::beg);
|
||||
|
||||
// Grab the string from the file
|
||||
gameDescriptor.assign((std::istreambuf_iterator<char>(file)),std::istreambuf_iterator<char>());
|
||||
|
||||
if( gameDescriptor.size() == 0 )
|
||||
{
|
||||
std::cerr<<"Error: failed to read in any information from "<<gameFile<<std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Create the game
|
||||
CTTRTSGame game = CTTRTSGame::CreateFromString(gameDescriptor);
|
||||
|
||||
// Grab the teams involved
|
||||
auto teams = game.GetTeams();
|
||||
|
||||
// Current game directory
|
||||
std::string gameDir = "ttrts_" + game.GetName();
|
||||
|
||||
// Remove the current game directory
|
||||
char cmd[128];
|
||||
snprintf(cmd,128, "test -e %s && rm -rf %s",gameDir.c_str(),gameDir.c_str());
|
||||
system(cmd);
|
||||
|
||||
// Create the game directory
|
||||
char cmd2[128];
|
||||
snprintf(cmd2,128, "mkdir %s",gameDir.c_str());
|
||||
system(cmd2);
|
||||
|
||||
// While the game hasn't been won
|
||||
Team winningTeam = Team::NUM_INVALID;
|
||||
while ( (winningTeam = game.CheckForWin()) == Team::NUM_INVALID )
|
||||
{
|
||||
// Create a turn file
|
||||
char turnFileName[128];
|
||||
snprintf(turnFileName,128,"ttrts_%s/Turn_%i.txt",game.GetName().c_str(),game.GetTurn());
|
||||
std::ofstream turnFile(turnFileName,std::ios::trunc); // truncate to overwrite if a file exists
|
||||
|
||||
if ( turnFile.bad() )
|
||||
{
|
||||
std::cerr<<"Error: Failed to open new turn file "<< turnFileName <<std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Output the turn description
|
||||
std::string turnDescriptor = game.GetStateAsString();
|
||||
turnFile<<turnDescriptor;
|
||||
turnFile.close();
|
||||
|
||||
// Wait for order files
|
||||
for( Team team : teams )
|
||||
{
|
||||
// Construct the team order filename
|
||||
char teamOrderFileName[128];
|
||||
snprintf(teamOrderFileName, 128, "ttrts_%s/Turn_%i_Team_%i.txt", game.GetName().c_str(), game.GetTurn(), (int) team);
|
||||
|
||||
// Wait for the team order file to be created
|
||||
std::cout<<"Waiting for "<<teamOrderFileName<<std::endl;
|
||||
WaitForFile(teamOrderFileName,sk_waitTime); // Wait for the file
|
||||
|
||||
std::ifstream turnFile(teamOrderFileName);
|
||||
|
||||
// Reserve the full order string
|
||||
std::string orders;
|
||||
turnFile.seekg(0, std::ios::end);
|
||||
orders.reserve(turnFile.tellg());
|
||||
turnFile.seekg(0, std::ios::beg);
|
||||
|
||||
// Grab the string from the file
|
||||
orders.assign((std::istreambuf_iterator<char>(turnFile)),std::istreambuf_iterator<char>());
|
||||
|
||||
// Issue the orders to the game
|
||||
if( game.IssueOrders(team, orders) )
|
||||
std::cerr<<"Warning: Orders for team "<<(int)team<<" failed to correctly parse"<<std::endl;
|
||||
}
|
||||
|
||||
// Simulate turn
|
||||
std::cerr<<"Simulating next turn"<<std::endl;
|
||||
if ( game.SimulateToNextTurn() )
|
||||
{
|
||||
std::cerr << "Error: Failed to simulate next Turn "<<game.GetTurn()<<std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Print the winner!
|
||||
std::cout<<"TTRTS: Game over! Winner:"<<(int)winningTeam<<std::endl;
|
||||
|
||||
return 0;
|
||||
};
|
Loading…
Add table
Reference in a new issue