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