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
		Add a link
		
	
		Reference in a new issue