Huge refactor, pulling server and local out into their own binaries
This commit is contained in:
parent
1b2010faba
commit
0ead12c7dd
16 changed files with 165 additions and 247 deletions
|
@ -3,45 +3,21 @@
|
||||||
project( ttrts-client )
|
project( ttrts-client )
|
||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
${CMAKE_CURRENT_BINARY_DIR}
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
../system
|
||||||
../ttrts
|
../ttrts
|
||||||
)
|
)
|
||||||
|
|
||||||
# Add the sources
|
# Add the sources
|
||||||
set( SOURCES
|
set( SOURCES
|
||||||
main.cpp
|
|
||||||
client.cpp
|
client.cpp
|
||||||
server.cpp
|
|
||||||
net.cpp
|
|
||||||
filesystem.cpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Set defaults for ttrts variables
|
|
||||||
set( TTRTS_MAPS "/usr/local/share/ttrts/maps/" )
|
|
||||||
set( TTRTS_GAMES "/tmp/" )
|
|
||||||
set( TTRTS_PORT 11715 )
|
|
||||||
|
|
||||||
# define these defaults in code
|
|
||||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTTRTS_MAPS=${TTRTS_MAPS}" )
|
|
||||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTTRTS_GAMES=${TTRTS_GAMES}" )
|
|
||||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTTRTS_PORT=${TTRTS_PORT}" )
|
|
||||||
|
|
||||||
# Add the executable
|
# Add the executable
|
||||||
add_executable( ${PROJECT_NAME} ${SOURCES} )
|
add_executable( ${PROJECT_NAME} ${SOURCES} )
|
||||||
|
|
||||||
# Set our output name to ttrts
|
|
||||||
set_target_properties( ${PROJECT_NAME} PROPERTIES OUTPUT_NAME ttrts )
|
|
||||||
|
|
||||||
# dependent on main ttrts libary
|
# dependent on main ttrts libary
|
||||||
target_link_libraries( ${PROJECT_NAME} ttrts pthread )
|
target_link_libraries( ${PROJECT_NAME} ttrts ttrts-system )
|
||||||
|
|
||||||
# Installation target
|
# Installation target
|
||||||
install( TARGETS ${PROJECT_NAME} DESTINATION bin )
|
install( TARGETS ${PROJECT_NAME} DESTINATION bin )
|
||||||
|
|
||||||
# Run the gen_usage script to generate our usage header
|
|
||||||
add_custom_target(
|
|
||||||
ttrts-client-usage
|
|
||||||
cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_SOURCE_DIR}/scripts/gen_usage.sh "${CMAKE_CURRENT_BINARY_DIR}/usage.h"
|
|
||||||
)
|
|
||||||
|
|
||||||
add_dependencies(${PROJECT_NAME} ttrts-client-usage)
|
|
||||||
|
|
|
@ -1,98 +0,0 @@
|
||||||
# NAME
|
|
||||||
ttrts - Tiny Terminal RTS
|
|
||||||
|
|
||||||
# SYNOPSIS
|
|
||||||
ttrts MAPFILE
|
|
||||||
|
|
||||||
# DESCRIPTION
|
|
||||||
ttrts is a tiny terminal based RTS that uses text files as order lists to control the units
|
|
||||||
|
|
||||||
This means that any user, program or cat that can read and write to text files can play the game
|
|
||||||
|
|
||||||
# RETURN VALUE
|
|
||||||
ttrts will return -1 on error, or the winning player on completion
|
|
||||||
|
|
||||||
# OPTIONS
|
|
||||||
MAPFILE - File to read in the initial game state. Local or in ${TTRTS_MAPS}
|
|
||||||
|
|
||||||
# USAGE
|
|
||||||
When invoked, ttrts will set up the game in a directory within ${TTRTS_GAMES} by the name of the map
|
|
||||||
|
|
||||||
The files in this directory can be read and interpreted by human, robot or cat
|
|
||||||
|
|
||||||
ttrts will then await order files from each participant
|
|
||||||
|
|
||||||
Once all order files have been received ttrts will calculate the turn and output a new gamestate file
|
|
||||||
|
|
||||||
This process repeats until the game is over
|
|
||||||
|
|
||||||
# ENVIRONMENT
|
|
||||||
${TTRTS_MAPS} - Map file lookup location, defaults to `/usr/share/ttrts/maps/`
|
|
||||||
|
|
||||||
${TTRTS_GAMES} - Game directory for I/O, defaults to `/tmp/`
|
|
||||||
|
|
||||||
-----------------------------------------------------------
|
|
||||||
# FILES
|
|
||||||
`/usr/share/ttrts/maps/` holds a sample set of maps
|
|
||||||
|
|
||||||
## Gamestate File
|
|
||||||
Turn_{TURNNUMBER}.txt
|
|
||||||
|
|
||||||
### Contents
|
|
||||||
===== ttrts v{MAJOR}.{MINOR}.{PATCH} =====
|
|
||||||
NAME:{GAMENAME}
|
|
||||||
SIZE:[{X},{Y}]
|
|
||||||
TURN:{TURNNUMBER}
|
|
||||||
WALL:[{X},{Y}][{X},{Y}][{X},{Y}]...{repeat for all walls}
|
|
||||||
~~~~
|
|
||||||
UNIT:{ID} pl:{PLAYER} vs:{VIS} dr:{DIR(NESW)} ps:[{X},{Y}]
|
|
||||||
... {continue for all units}
|
|
||||||
END
|
|
||||||
|
|
||||||
## Order File
|
|
||||||
Player_{PLAYER_ID}_Turn_{TURN_NUMBER}.txt
|
|
||||||
|
|
||||||
### Contents
|
|
||||||
ORDER:{ORDER_CHAR} id:{UNIT_ID}
|
|
||||||
... {continue for all orders}
|
|
||||||
END
|
|
||||||
|
|
||||||
-----------------------------------------------------------
|
|
||||||
# GAMEPLAY
|
|
||||||
|
|
||||||
The game takes place in a series of simultaneous turns on an arbitrarily sized 2D board
|
|
||||||
|
|
||||||
Each turn, the client outputs a gamestate file and waits for an order file from each player
|
|
||||||
|
|
||||||
All commands are evaluated simultaneously with friendly fire enabled by default
|
|
||||||
|
|
||||||
The game is over when any of three conditions are met -
|
|
||||||
* All remaining units are controlled by a single player
|
|
||||||
* No units are left (draw)
|
|
||||||
* All units left are unable to move (draw)
|
|
||||||
|
|
||||||
# UNITS
|
|
||||||
Each unit occupies a single tile on the board, facing in a compass direction (NESW)
|
|
||||||
|
|
||||||
Units will only accept orders from their owner
|
|
||||||
|
|
||||||
Units can receive only a single order each turn
|
|
||||||
|
|
||||||
Units cannot occupy the same tile as other units/walls
|
|
||||||
|
|
||||||
# ORDERS
|
|
||||||
### F - Move unit [F]orward one space, leaving a wall
|
|
||||||
|
|
||||||
This wall will remain until the end of the game, blocking movement to that tile
|
|
||||||
|
|
||||||
Movement orders have no effect if impossible, eg.
|
|
||||||
* Attempting to move outside of map
|
|
||||||
* Attempting to move on to tile occupied by unit/wall
|
|
||||||
|
|
||||||
### L/R - Rotate unit [L]eft or [R]ight
|
|
||||||
|
|
||||||
Unit will rotate clockwise or counter-clockwise, this order cannot fail
|
|
||||||
|
|
||||||
### A - [A]ttack in straight line in front of unit
|
|
||||||
|
|
||||||
Attack will continue forward until unit can't progress, all units within the path of the attack are destroyed.
|
|
|
@ -1,17 +1,15 @@
|
||||||
#include "client.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
|
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
|
#include "error.h"
|
||||||
#include "filesystem.h"
|
#include "filesystem.h"
|
||||||
|
|
||||||
int runClient(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
// must provide information
|
// must provide information
|
||||||
if (argc < 2)
|
if (argc < 2)
|
||||||
fatal_error("Usage: ttrts client HOST");
|
fatal_error("Usage: ttrts-client HOST");
|
||||||
|
|
||||||
std::string hostname = argv[1];
|
std::string hostname = argv[1];
|
||||||
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
#ifndef _TTRTS_CLIENT_H_
|
|
||||||
#define _TTRTS_CLIENT_H_
|
|
||||||
|
|
||||||
int runClient(int argc, char* argv[]);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,34 +0,0 @@
|
||||||
#include "game.h"
|
|
||||||
#include "filesystem.h"
|
|
||||||
#include "server.h"
|
|
||||||
#include "client.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
static const char* sk_usage =
|
|
||||||
#include "usage.h"
|
|
||||||
;
|
|
||||||
|
|
||||||
// Main program entry point
|
|
||||||
int main(int argc, char* argv[])
|
|
||||||
{
|
|
||||||
// If no args, print usage
|
|
||||||
if ( argc == 1 )
|
|
||||||
{
|
|
||||||
std::cout<<sk_usage<<std::endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attempt to open the game file
|
|
||||||
std::string arg1 = argv[1];
|
|
||||||
|
|
||||||
// Either run the client, the server, or from local filesystem
|
|
||||||
if( arg1 == "client" )
|
|
||||||
return runClient(argc-1,argv+1);
|
|
||||||
else if ( arg1 == "server" )
|
|
||||||
return runServer(argc-1,argv+1);
|
|
||||||
else
|
|
||||||
return runFromFilesystem(argc,argv);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
#ifndef _TTRTS_SERVER_H_
|
|
||||||
#define _TTRTS_SERVER_H_
|
|
||||||
|
|
||||||
int runServer(int argc, char* argv[]);
|
|
||||||
|
|
||||||
#endif
|
|
23
source/local/CMakeLists.txt
Normal file
23
source/local/CMakeLists.txt
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
# ====================== ttrts =======================
|
||||||
|
# Project name
|
||||||
|
project( ttrts-local )
|
||||||
|
|
||||||
|
include_directories(
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
../system
|
||||||
|
../ttrts
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add the sources
|
||||||
|
set( SOURCES
|
||||||
|
local.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add the executable
|
||||||
|
add_executable( ${PROJECT_NAME} ${SOURCES} )
|
||||||
|
|
||||||
|
# dependent on main ttrts libary
|
||||||
|
target_link_libraries( ${PROJECT_NAME} ttrts ttrts-system pthread )
|
||||||
|
|
||||||
|
# Installation target
|
||||||
|
install( TARGETS ${PROJECT_NAME} DESTINATION bin )
|
62
source/local/local.cpp
Normal file
62
source/local/local.cpp
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
#include "game.h"
|
||||||
|
#include "filesystem.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "net.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
// =====================================================================================================================
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
// must provide information
|
||||||
|
if (argc < 2)
|
||||||
|
fatal_error("Usage: ttrts-local MAPFILE");
|
||||||
|
|
||||||
|
std::string gamefile = argv[1];
|
||||||
|
|
||||||
|
std::cout<<"TTRTS: Launching with "<<gamefile<<std::endl;
|
||||||
|
CTTRTSGame game = GetGameFromFile(gamefile);
|
||||||
|
|
||||||
|
// Grab the players involved
|
||||||
|
auto players = game.GetPlayers();
|
||||||
|
|
||||||
|
// Default for games
|
||||||
|
std::string ttrts_games_dir = getGamesDir();
|
||||||
|
|
||||||
|
// Empty the current game directory
|
||||||
|
if ( CreateAndCleanGameDir(game.GetName()) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
// While the game isn't finished
|
||||||
|
while ( ! game.GameOver() )
|
||||||
|
{
|
||||||
|
std::cout<<"TTRTS: Starting turn "<<game.GetTurn()<<std::endl;
|
||||||
|
|
||||||
|
// Create a turn file
|
||||||
|
if( !OutputGameStateFile(game))
|
||||||
|
fatal_error("Error: Failed to output new turn file");
|
||||||
|
|
||||||
|
// Wait for order files
|
||||||
|
for( player_t player : players)
|
||||||
|
{
|
||||||
|
// Construct the player order filename
|
||||||
|
std::string orders = GetOrdersFromPlayerFile(game, player);
|
||||||
|
|
||||||
|
// Issue the orders to the game
|
||||||
|
if( game.IssueOrders(player, orders) )
|
||||||
|
std::cerr<<"Warning: Orders for player "<<(int) player <<" failed to correctly parse"<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simulate turn
|
||||||
|
std::cout<<"TTRTS: Simulating this turn!"<<std::endl;
|
||||||
|
if ( game.SimulateToNextTurn() )
|
||||||
|
fatal_error("Failed to simulate game turn");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output final gamestate
|
||||||
|
OutputGameStateFile(game);
|
||||||
|
|
||||||
|
return OutputGameEnd( game );
|
||||||
|
}
|
||||||
|
|
23
source/server/CMakeLists.txt
Normal file
23
source/server/CMakeLists.txt
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
# ====================== ttrts =======================
|
||||||
|
# Project name
|
||||||
|
project( ttrts-server )
|
||||||
|
|
||||||
|
include_directories(
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
../system
|
||||||
|
../ttrts
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add the sources
|
||||||
|
set( SOURCES
|
||||||
|
server.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add the executable
|
||||||
|
add_executable( ${PROJECT_NAME} ${SOURCES} )
|
||||||
|
|
||||||
|
# dependent on main ttrts libary
|
||||||
|
target_link_libraries( ${PROJECT_NAME} ttrts ttrts-system pthread )
|
||||||
|
|
||||||
|
# Installation target
|
||||||
|
install( TARGETS ${PROJECT_NAME} DESTINATION bin )
|
|
@ -1,4 +1,4 @@
|
||||||
#include "server.h"
|
#include "error.h"
|
||||||
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -80,11 +80,11 @@ void RunServerForGame(CTTRTSGame &game)
|
||||||
SendGamestateToClients(myClients, game, gameMutex);
|
SendGamestateToClients(myClients, game, gameMutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
int runServer(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
// argv[1] needs to be a valid game file
|
// argv[1] needs to be a valid game file
|
||||||
if( argc < 2 )
|
if( argc < 2 )
|
||||||
fatal_error("must provide game file argument");
|
fatal_error("Usage: ttrts-server MAPFILE");
|
||||||
|
|
||||||
// Set up game
|
// Set up game
|
||||||
CTTRTSGame game = GetGameFromFile(argv[1]);
|
CTTRTSGame game = GetGameFromFile(argv[1]);
|
21
source/system/CMakeLists.txt
Normal file
21
source/system/CMakeLists.txt
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
cmake_minimum_required(VERSION 2.8.7)
|
||||||
|
|
||||||
|
# Main ttrts library
|
||||||
|
project( ttrts-system )
|
||||||
|
|
||||||
|
# Include the maths
|
||||||
|
include_directories(
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
../ttrts
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add our sources
|
||||||
|
set( SOURCES
|
||||||
|
net.cpp
|
||||||
|
filesystem.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add this library
|
||||||
|
add_library( ${PROJECT_NAME} ${SOURCES} )
|
||||||
|
|
||||||
|
target_link_libraries( ${PROJECT_NAME} ttrts pthread )
|
25
source/system/error.h
Normal file
25
source/system/error.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#ifndef _TTRTS_ERROR_H_
|
||||||
|
#define _TTRTS_ERROR_H_
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
//======================================================================================================================
|
||||||
|
// Error functions
|
||||||
|
|
||||||
|
// For local fatal errors
|
||||||
|
inline void fatal_error(const char *msg)
|
||||||
|
{
|
||||||
|
std::cerr<<msg<<std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// For system fatal errors (ie. functions that set errno)
|
||||||
|
inline void fatal_perror(const char *msg)
|
||||||
|
{
|
||||||
|
perror(msg);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,5 +1,6 @@
|
||||||
#include "filesystem.h"
|
#include "filesystem.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
|
#include "error.h"
|
||||||
|
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
@ -245,54 +246,3 @@ int OutputgameEnd(const CTTRTSGame &game) {
|
||||||
|
|
||||||
return (int)winningPlayer;
|
return (int)winningPlayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
// =====================================================================================================================
|
|
||||||
int runFromFilesystem(int argc, char* argv[])
|
|
||||||
{
|
|
||||||
std::string gamefile = argv[1];
|
|
||||||
|
|
||||||
std::cout<<"TTRTS: Launching with "<<gamefile<<std::endl;
|
|
||||||
CTTRTSGame game = GetGameFromFile(gamefile);
|
|
||||||
|
|
||||||
// Grab the players involved
|
|
||||||
auto players = game.GetPlayers();
|
|
||||||
|
|
||||||
// Default for games
|
|
||||||
std::string ttrts_games_dir = getGamesDir();
|
|
||||||
|
|
||||||
// Empty the current game directory
|
|
||||||
if ( CreateAndCleanGameDir(game.GetName()) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
// While the game isn't finished
|
|
||||||
while ( ! game.GameOver() )
|
|
||||||
{
|
|
||||||
std::cout<<"TTRTS: Starting turn "<<game.GetTurn()<<std::endl;
|
|
||||||
|
|
||||||
// Create a turn file
|
|
||||||
if( !OutputGameStateFile(game))
|
|
||||||
fatal_error("Error: Failed to output new turn file");
|
|
||||||
|
|
||||||
// Wait for order files
|
|
||||||
for( player_t player : players)
|
|
||||||
{
|
|
||||||
// Construct the player order filename
|
|
||||||
std::string orders = GetOrdersFromPlayerFile(game, player);
|
|
||||||
|
|
||||||
// Issue the orders to the game
|
|
||||||
if( game.IssueOrders(player, orders) )
|
|
||||||
std::cerr<<"Warning: Orders for player "<<(int) player <<" failed to correctly parse"<<std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Simulate turn
|
|
||||||
std::cout<<"TTRTS: Simulating this turn!"<<std::endl;
|
|
||||||
if ( game.SimulateToNextTurn() )
|
|
||||||
fatal_error("Failed to simulate game turn");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Output final gamestate
|
|
||||||
OutputGameStateFile(game);
|
|
||||||
|
|
||||||
return OutputGameEnd( game );
|
|
||||||
}
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
|
#include "error.h"
|
||||||
|
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
|
|
@ -74,23 +74,6 @@ std::string WaitForGamestateMessage(int sockfd);
|
||||||
// Send orders to the server
|
// Send orders to the server
|
||||||
int SendOrdersToServer(int sockfd, const std::string &orders);
|
int SendOrdersToServer(int sockfd, const std::string &orders);
|
||||||
|
|
||||||
//======================================================================================================================
|
|
||||||
// Error functions
|
|
||||||
|
|
||||||
// For local fatal errors
|
|
||||||
inline void fatal_error(const char *msg)
|
|
||||||
{
|
|
||||||
std::cerr<<msg<<std::endl;
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// For system fatal errors (ie. functions that set errno)
|
|
||||||
inline void fatal_perror(const char *msg)
|
|
||||||
{
|
|
||||||
perror(msg);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
//======================================================================================================================
|
//======================================================================================================================
|
||||||
// Other functions
|
// Other functions
|
||||||
int OutputGameEnd( CTTRTSGame& game );
|
int OutputGameEnd( CTTRTSGame& game );
|
Loading…
Add table
Reference in a new issue