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;
|
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
|
// Check if we have a win state
|
||||||
Team CTTRTSGame::CheckForWin() const
|
Team CTTRTSGame::CheckForWin() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -96,6 +96,10 @@ public:
|
||||||
|
|
||||||
// Set the turn of the game
|
// Set the turn of the game
|
||||||
inline int SetTurn( int in ) { return (turn = in); }
|
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:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,17 @@
|
||||||
# Project name
|
# Project name
|
||||||
project( ttrts )
|
project( ttrts )
|
||||||
|
|
||||||
|
include_directories(
|
||||||
|
../maths
|
||||||
|
../game
|
||||||
|
)
|
||||||
|
|
||||||
# Add the sources
|
# Add the sources
|
||||||
set( SOURCES
|
set( SOURCES
|
||||||
main.cpp
|
main.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# Add the executable
|
# Add the executable
|
||||||
add_executable( ttrts ${SOURCES} )
|
add_executable( ttrts ${SOURCES} )
|
||||||
|
|
||||||
|
target_link_libraries( ttrts game )
|
|
@ -1,5 +1,156 @@
|
||||||
// Main program entry point
|
#include <iostream>
|
||||||
int main()
|
#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;
|
return 0;
|
||||||
};
|
};
|
Loading…
Add table
Reference in a new issue