diff --git a/.gitignore b/.gitignore index bbb848f..6b267c4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,3 @@ -# Base directories -/bin -/lib -/build -/work - # prepend '__' to create temp files/dirs __* @@ -16,6 +10,7 @@ __* .#* notes* TAGS +*.swp # Haskell-related # ################### diff --git a/Authors.txt b/Authors.txt index 755ff70..99503fa 100644 --- a/Authors.txt +++ b/Authors.txt @@ -2,5 +2,6 @@ The Red Spider Project -- Authors.txt (Please add your name at the top.) +Charles Mita Harry Gilles Julian Gonggrijp diff --git a/bin/.gitignore b/bin/.gitignore new file mode 100644 index 0000000..7ff134a --- /dev/null +++ b/bin/.gitignore @@ -0,0 +1,3 @@ +#Ignore this directory except this file +* +!.gitignore diff --git a/build/.gitignore b/build/.gitignore new file mode 100644 index 0000000..7ff134a --- /dev/null +++ b/build/.gitignore @@ -0,0 +1,3 @@ +#Ignore this directory except this file +* +!.gitignore diff --git a/include/rsTerminal.h b/include/rsTerminal.h new file mode 100644 index 0000000..fc8b0aa --- /dev/null +++ b/include/rsTerminal.h @@ -0,0 +1,37 @@ +#ifndef RS_TERMINAL_H +#define RS_TERMINAL_H +#include "rsTypes.h" +#ifdef _WIN32 +#include +#endif + + +enum terminalColours_t { + COLOUR_DEFAULT = 0, + COLOUR_BLUE = 1, + COLOUR_GREEN = 2, + COLOUR_RED = 4, + COLOUR_WHITE = 8 +}; + +class rsTerminal +{ + public: + rsTerminal(); + ~rsTerminal(); + void ClearTerminal(); + void SetCursorPosition( rsCOORD_t pos ); + void SetTextColour( int terminalColour ); + //void PrintText( const char * text ); + void SetToDefault(); + void HideCursor(); + void ShowCursor(); + private: + #ifdef _WIN32 + CONSOLE_SCREEN_BUFFER_INFO defaultBufferInfo; + HANDLE hStdOut; + #endif + +}; + +#endif diff --git a/include/rsTypes.h b/include/rsTypes.h new file mode 100644 index 0000000..406b2df --- /dev/null +++ b/include/rsTypes.h @@ -0,0 +1,9 @@ +#ifndef RS_TYPES_H +#define RS_TYPES_H + +struct rsCOORD_t { + int x; + int y; +}; + +#endif \ No newline at end of file diff --git a/lib/.gitignore b/lib/.gitignore new file mode 100644 index 0000000..7ff134a --- /dev/null +++ b/lib/.gitignore @@ -0,0 +1,3 @@ +#Ignore this directory except this file +* +!.gitignore diff --git a/src/makefile b/src/makefile new file mode 100644 index 0000000..1f9e189 --- /dev/null +++ b/src/makefile @@ -0,0 +1,23 @@ +CC=g++ +CFLAGS=-O3 -I../include -std=c++11 -pthread + +IDIR = ../include +ODIR = ../build +BDIR = ../bin + +_DEPS = rsTypes.h rsTerminal.h +DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS)) + +_OBJ = rsGameOfLife.o rsTerminal.o +OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ)) + +$(ODIR)/%.o: %.cpp $(DEPS) + $(CC) -c -o $@ $< $(CFLAGS) + +gameofspiders: $(OBJ) + $(CC) -o $(BDIR)/$@ $^ $(CFLAGS) $(LIBS) + +.PHONY: clean + +clean: + rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~d diff --git a/src/rsGameOfLife.cpp b/src/rsGameOfLife.cpp new file mode 100644 index 0000000..ced2c6f --- /dev/null +++ b/src/rsGameOfLife.cpp @@ -0,0 +1,560 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "rsTerminal.h" +#include "rsTypes.h" + +enum universeType_t { + TORUS, + KLEIN, + SPHERE, + PROJ +}; + +enum cellState_t { + STATE_RED, + STATE_BLUE, + STATE_DEAD, + STATE_OTHER //debug value +}; + +class rsUniverse +{ +public: + unsigned int offsetX; + unsigned int offsetY; + unsigned int probBlue; + unsigned int probRed; + rsUniverse( const int x, const int y ) + { + univCurrent = new cellState_t[ x * y ]; + univPrev = new cellState_t[ x * y ]; + boundX = x; + boundY = y; + probBlue = 7; + probRed = 7; + offsetX = 0; + offsetY = 0; + } + + ~rsUniverse() + { + delete [] univCurrent; + delete [] univPrev; + } + + void SeedUniverse( int seed ) + { + srand( seed ); + for( int i = 0; i < boundX * boundY; i++ ) { + int randNumber = rand() % 100; + univCurrent[i] = randNumber < probBlue ? STATE_BLUE : + randNumber < probBlue + probRed ? STATE_RED : STATE_DEAD; + } + } + + void NextState() + { + cellState_t* temp = univPrev; + univPrev = univCurrent; + univCurrent = temp; + + for ( int x = 0 ; x < boundX ; x++ ) { + for ( int y = 0 ; y < boundY ; y++ ) { + rsCOORD_t point = { x , y }; + univCurrent[ x * boundY + y ] = CalcState( point ); + } + } + } + + void DrawUniverse( rsTerminal * terminal ) const + { + rsCOORD_t cursor; + for ( int x = 0 ; x < boundX ; x++ ) { + cursor.x = x + offsetX; + for (int y = 0 ; y < boundY ; y++ ) { + cursor.y = y + offsetY; + //always draw the top left cell, to prevent screen scrolling on Windows + if ( ( x == 0 && y == 0 ) || univCurrent[ x * boundY + y ] != univPrev[ x * boundY + y ] ) { + switch ( univCurrent[ x * boundY + y ] ) { + case STATE_DEAD: + terminal->SetCursorPosition( cursor ); + std::cout<<" "; + break; + case STATE_BLUE: + terminal->SetTextColour( COLOUR_BLUE | COLOUR_WHITE | COLOUR_GREEN ); + terminal->SetCursorPosition( cursor ); + std::cout<<"O"; + break; + case STATE_RED: + terminal->SetTextColour( COLOUR_RED | COLOUR_WHITE ); + terminal->SetCursorPosition( cursor ); + std::cout<<"X"; + break; + default: + terminal->SetTextColour( COLOUR_GREEN | COLOUR_WHITE ); + terminal->SetCursorPosition( cursor ); + std::cout<<"Z"; + } + } + } + std::cout << std::flush; + } + } + + void DrawBorder ( rsTerminal * terminal ) const + { + //only draw border if a margin has been set + if ( offsetX == 0 || offsetY == 0 ) return; + rsCOORD_t point; + terminal->SetTextColour( COLOUR_BLUE ); + //top and bottom + for ( int x = 0; x <= boundX; x++ ) { + point.x = offsetX + x - 1; + point.y = offsetY - 1; + terminal->SetCursorPosition(point); + std::cout<<"-"; + point.y = offsetY + boundY; + terminal->SetCursorPosition(point); + std::cout<<"-"; + } + //sides + for ( int y = 0; y <= boundY; y++ ) { + point.y = offsetY + y - 1; + point.x = offsetX - 1; + terminal->SetCursorPosition(point); + std::cout<<"|"; + point.x = offsetX + boundX; + terminal->SetCursorPosition(point); + std::cout<<"|"; + } + //corners + point.x = offsetX - 1; + point.y = offsetY - 1; + terminal->SetCursorPosition(point); + std::cout<<"/"; + point.x += boundX + 1; + terminal->SetCursorPosition(point); + std::cout<<"\\"; + point.y += boundY + 1; + terminal->SetCursorPosition(point); + std::cout<<"/"; + point.x -= (boundX + 1); + terminal->SetCursorPosition(point); + std::cout<<"\\"; + } + +protected: + cellState_t* univCurrent; + cellState_t* univPrev; + int boundX; + int boundY; + + virtual void GetNeighbourhood( const rsCOORD_t point, cellState_t neighbourhood[3][3] ) const = 0; + + cellState_t CalcState( const rsCOORD_t point ) + { + int countB = 0; + int countR = 0; + cellState_t neighbourhood[3][3]; + GetNeighbourhood( point, neighbourhood ); + for ( int i = 0 ; i < 3 ; i += 2 ) { + for ( int j = 0; j < 3 ; j++ ) { + switch ( neighbourhood[i][j] ) { + case STATE_BLUE: + countB++; + break; + case STATE_RED: + countR++; + break; + } + + } + } + if ( neighbourhood[1][0] == STATE_BLUE ) countB++; + if ( neighbourhood[1][0] == STATE_RED ) countR++; + if ( neighbourhood[1][2] == STATE_BLUE ) countB++; + if ( neighbourhood[1][2] == STATE_RED ) countR++; + + switch ( neighbourhood[1][1] ) { + case STATE_DEAD: + if ( ( countR + countB ) == 3 ) { + return countB > countR ? STATE_BLUE : STATE_RED; + } + return ( ( countR + countB == 6 ) && countR > countB ) ? STATE_RED : STATE_DEAD; + case STATE_RED: + return ( (countR + countB > 3) || (countR + countB < 2) ) ? STATE_DEAD : STATE_RED ; + case STATE_BLUE: + return ( (countR + countB > 3) || (countR + countB < 2) ) ? STATE_DEAD : STATE_BLUE ; + default: + return STATE_OTHER; + } + } +}; + +class rsUniverseTorus: public rsUniverse +{ +public: + rsUniverseTorus( const int x, const int y ) : rsUniverse( x, y ) {}; +private: + void GetNeighbourhood( const rsCOORD_t point, cellState_t neighbourhood[3][3] ) const + { + for ( int i = 0 ; i < 3 ; i++ ) { + for ( int j = 0; j < 3 ; j++ ) { + int x = ( point.x + i - 1 ) % boundX; + int y = ( point.y + j - 1 ) % boundY; + if ( x < 0 ) { x += boundX; } + if ( y < 0 ) { y += boundY; } + neighbourhood[i][j] = univPrev[ x * boundY + y ]; + } + } + } +}; + +class rsUniverseKlein: public rsUniverse +{ +public: + rsUniverseKlein( const int x, const int y ) : rsUniverse( x, y ) {}; +private: + void GetNeighbourhood( const rsCOORD_t point, cellState_t neighbourhood[3][3] ) const + { + for ( int i = 0; i < 3; i++ ) { + for ( int j = 0; j < 3; j++ ) { + int x = ( point.x + i - 1 ); + int y; + if ( -1 == x || boundX == x ) { + y = ( boundY - point.y - j ) % boundY; + } else { + y = ( point.y + j + - 1 ) % boundY; + } + x %= boundX; + if ( x < 0 ) { x += boundX; } + if ( y < 0 ) { y += boundY; } + neighbourhood[i][j] = univPrev[ x * boundY + y]; + } + } + } +}; + +class rsUniverseSphere: public rsUniverse +{ +public: + rsUniverseSphere( const int x ) : rsUniverse( x, x ) {}; +private: + void GetNeighbourhood( const rsCOORD_t point, cellState_t neighbourhood[3][3] ) const + { + enum univPolePositions_t { NORMAL, NORTH_0, NORTH_X, NORTH_Y, SOUTH_0, SOUTH_X, SOUTH_Y }; + univPolePositions_t positions = NORMAL; + if ( point.x == 0 && point.y == 0 ) positions = NORTH_0; + if ( point.x == 0 && point.y == 1 ) positions = NORTH_Y; + if ( point.x == 1 && point.y == 0 ) positions = NORTH_X; + if ( point.x == boundX - 1 && point.y == boundY - 1 ) positions = SOUTH_0; + if ( point.x == boundX - 1 && point.y == boundY - 2 ) positions = SOUTH_Y; + if ( point.x == boundX - 2 && point.y == boundY - 1 ) positions = SOUTH_X; + + switch ( positions ) { + case NORMAL: + for ( int i = 0; i < 3; i++ ){ + for ( int j = 0; j < 3; j++ ) { + int x = point.x + i - 1; + int y = point.y + j - 1; + if ( x < 0 ) { + x = y; + y = 0; + } + if ( y < 0 ) { + y = x; + x = 0; + } + if ( x == boundX ) { + x = y; + y = boundY - 1; + } + if ( y == boundY ) { + y = x; + x = boundX - 1; + } + neighbourhood[i][j] = univPrev[ x * boundY + y ]; + } + } + break; + case NORTH_0: + for ( int i = 0; i < 2; i++ ){ + for ( int j = 0; j < 2; j++ ) { + neighbourhood[ i + 1 ][ j + 1 ] = univPrev[ i * boundY + j ]; + } + } + break; + case NORTH_Y: + for ( int i = 0; i < 2; i++ ){ + for ( int j = 0; j < 3; j++ ) { + neighbourhood[ i + 1 ][j] = univPrev[ i * boundY + j ]; + } + } + neighbourhood[0][2] = univPrev[ 2 * boundX + 0 ]; + break; + case NORTH_X: + for ( int i = 0; i < 3; i++ ){ + for ( int j = 0; j < 2; j++ ) { + neighbourhood[i][ j + 1 ] = univPrev[ i * boundY+ j ]; + } + } + neighbourhood[2][0] = univPrev[2]; //this is wrong? + break; + case SOUTH_0: + for ( int i = 0; i < 2; i++ ) { + for ( int j = 0; j < 2; j++ ) { + neighbourhood[i][j] = univPrev[ (boundX - 2 + i) * boundY + (boundY - 2 + j) ]; + } + } + break; + case SOUTH_Y: + for ( int i = 0; i < 2; i++ ){ + for ( int j = 0; j < 3; j++ ) { + neighbourhood[i][j] = univPrev[ (boundX - 2 + i) * boundY + (boundY - 3 + j) ]; + } + } + neighbourhood[2][0] = univPrev[ (boundX - 3) * boundY + (boundY - 1) ]; + break; + case SOUTH_X: + for ( int i = 0; i < 3; i++ ){ + for ( int j = 0; j < 2; j++ ) { + neighbourhood[i][j] = univPrev[ (boundX - 3 + i) * boundY + (boundY - 2 + j) ]; + } + } + neighbourhood[0][2] = univPrev[ (boundX - 1) * boundY + (boundY - 3) ]; + break; + } + return; + } +}; + +class rsUniverseProj: public rsUniverse +{ +public: + rsUniverseProj( const int x, const int y ) : rsUniverse( x, y ) {}; +private: + void GetNeighbourhood( const rsCOORD_t point, cellState_t neighbourhood[3][3] ) const + { + enum univCorner_t { NONE, TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT }; + univCorner_t corner = NONE; + if ( point.x == 0 && point.y == 0 ) corner = TOP_LEFT; + if ( point.x == 0 && point.y == boundY - 1 ) corner = TOP_RIGHT; + if ( point.x == boundX - 1 && point.y == 0 ) corner = BOTTOM_LEFT; + if ( point.x == boundX - 1 && point.y == boundY - 1 ) corner = BOTTOM_RIGHT; + switch ( corner ) { + case NONE: + for ( int i = 0; i < 3; i++ ){ + for ( int j = 0; j < 3; j++ ) { + int x = point.x + i - 1; + int y = point.y + j - 1; + if ( -1 == x || boundX == x ) { + x = ( -1 == x ? boundX - 1 : 0 ); + y = boundY - 1 - y; + } + if ( -1 == y || boundY == y ) { + y = ( -1 == y ? boundY - 1 : 0 ); + x = boundX - 1 - x; + } + neighbourhood[i][j] = univPrev[ x * boundY + y ]; + } + } + break; + case TOP_LEFT: + for ( int i = 0; i < 2; i++ ){ + for ( int j = 0; j < 2; j++ ) { + neighbourhood[ i + 1 ][ j + 1 ] = univPrev[ i * boundY + j ]; + } + } + neighbourhood[0][1] = univPrev[ (boundX - 1) * boundY + (boundY - 1) ]; + neighbourhood[0][2] = univPrev[ (boundX - 1) * boundY + (boundY - 2) ]; + neighbourhood[2][0] = univPrev[ (boundX - 2) * boundY + (boundY - 1) ]; + break; + case TOP_RIGHT: + for ( int i = 0; i < 2; i++ ){ + for ( int j = 0; j < 2; j++ ) { + neighbourhood[ i + 1 ][j] = univPrev[ i * boundY + boundY - 2 + j ]; + } + } + neighbourhood[0][0] = univPrev[ (boundX - 1) * boundY + 1 ]; + neighbourhood[0][1] = univPrev[ (boundX - 1) * boundY + 0 ]; + neighbourhood[2][2] = univPrev[ (boundX - 2) * boundY + 0 ]; + break; + case BOTTOM_LEFT: + for ( int i = 0; i < 2; i++ ){ + for ( int j = 0; j < 2; j++ ) { + neighbourhood[i][j] = univPrev[ (boundX - 2 + i) * boundY + j ]; + } + } + neighbourhood[0][0] = univPrev[ 1 * boundY + boundY - 1 ]; + neighbourhood[0][1] = univPrev[ 0 * boundY + boundY - 1 ]; + neighbourhood[2][2] = univPrev[ 0 * boundY + boundY - 2 ]; + break; + case BOTTOM_RIGHT: + for ( int i = 0; i < 2; i++ ){ + for ( int j = 0; j < 2; j++ ) { + neighbourhood[i][j] = univPrev[ (boundX - 2 + i) * boundY + boundY - 2 + j ]; + } + } + neighbourhood[2][0] = univPrev[1]; + neighbourhood[2][1] = univPrev[0]; + neighbourhood[0][2] = univPrev[1 * boundY]; + break; + } + return; + } +}; + +void Interrupt( bool* stop ) +{ + getchar(); + *stop = true; + return; +} + +void SetupFromArgs( + std::vector args, + int* sizeX, + int* sizeY, + int* period, + rsUniverse** universe, + int* seed, + bool* printHelp, + bool* printArgs ) +{ + universeType_t univType = TORUS; + for ( auto it = args.begin(); it != args.end(); it++ ) { + if ( *it == "-H" || *it == "-h" || *it == "--help" ) { + *printHelp = true; + return; + } + if ( *it == "-A" || *it == "-a" ) { + *printArgs = true; + return; + } + if ( (*it)[0] == '-' ) { + if ( it + 1 == args.end() ) { + throw std::exception(); + } + std::string type; + std::string sizeString; + switch ( (*it)[1] ) { + case 'U': + type = *( it + 1 ); + if ( type == "K" || type == "k" ) univType = KLEIN; + if ( type == "S" || type == "s" ) univType = SPHERE; + if ( type == "P" || type == "p" ) univType = PROJ; + break; + case 'X': + sizeString = *( it + 1 ); + *sizeX = std::stoi( sizeString ); + break; + case 'Y': + sizeString = *( it + 1 ); + *sizeY = std::stoi( sizeString ); + break; + case 'P': + sizeString = *( it + 1 ); + *period = std::stoi( sizeString ); + break; + case 'S': + sizeString = *( it + 1 ); + *seed = std::stoi( sizeString ); + break; + } + } + } + switch (univType) { + case TORUS: + *universe = new rsUniverseTorus( *sizeX, *sizeY ); + break; + case KLEIN: + *universe = new rsUniverseKlein( *sizeX, *sizeY ); + break; + case SPHERE: + *universe = new rsUniverseSphere( *sizeX ); + break; + case PROJ: + *universe = new rsUniverseProj( *sizeX, *sizeY ); + break; + } +} + +void PrintHelp( bool argsOnly ) +{ + std::string arguments[5]; + arguments[0] = "-X [n] -Y [n] : specify dimensions"; + arguments[1] = "-U [T, K, S, P] : specify topology (toroidal, klein, spherical, projective plane)"; + arguments[2] = "-A : list arguments"; + arguments[3] = "-H : show full help"; + arguments[4] = "-P : set minimum time period between frames"; + + std::string copyright = "Copyright Charles Mita 2014.\n" + "Part of the Red Spider Project, licensed under the Red Spider Project License.\n" + "See License.txt that shipped with your copy of the software for details.\n"; + + std::string preface = "Game of Spiders is an implementation of Conway's Game of Life" + " and a variant, Highlife, using two distinct species.\n" + "File based starting arrangements coming at some point.\n"; + + std::cout << std::endl; + if ( !argsOnly ) { + std::cout << preface << std::endl; + std::cout << copyright << std::endl; + } + for ( int i = 0; i < 5; i++ ) { + std::cout << arguments[i] << std::endl; + } + std::cout << std::endl; + return; +} + +int main( int argc, char* argv[] ) +{ + rsUniverse* pUniverse; + int sizeX = 60; + int sizeY = 30; + int period = 60; + int seed = 7823641; + bool printHelp = false; + bool printArgs = false; + std::vector args( argv, argv + argc ); + SetupFromArgs( args, &sizeX, &sizeY, &period, &pUniverse, &seed, &printHelp, &printArgs ); + + if ( printArgs || printHelp ) { + PrintHelp( !printHelp ); + return 0; + } + + pUniverse->SeedUniverse( seed ); + pUniverse->offsetX = 5; + pUniverse->offsetY = 2; + rsTerminal terminal; + terminal.ClearTerminal(); + terminal.HideCursor(); + bool stop = false; + std::thread interruptThread( Interrupt, &stop ); + pUniverse->DrawBorder( &terminal ); + while ( !stop ) { + auto startTime = std::chrono::steady_clock::now(); + pUniverse->DrawUniverse( &terminal ); + pUniverse->NextState(); + auto endTime = std::chrono::steady_clock::now(); + int timeDiff = std::chrono::duration_cast( endTime - startTime ).count(); + int delay = period > timeDiff ? period - timeDiff : period; + std::this_thread::sleep_for( std::chrono::milliseconds( delay ) ); + } + interruptThread.join(); + terminal.ShowCursor(); + int posX = 0; + int posY = pUniverse->offsetY + sizeY + 2; + rsCOORD_t cursor = { posX, posY }; + terminal.SetCursorPosition( cursor ); + terminal.SetToDefault(); + return 0; +} diff --git a/src/rsTerminal.cpp b/src/rsTerminal.cpp new file mode 100644 index 0000000..4060b27 --- /dev/null +++ b/src/rsTerminal.cpp @@ -0,0 +1,101 @@ +#ifdef _WIN32 +#include +#else +#include +#endif +#include "rsTerminal.h" + +rsTerminal::rsTerminal() +{ + #ifdef _WIN32 + hStdOut = GetStdHandle( STD_OUTPUT_HANDLE ); + GetConsoleScreenBufferInfo( hStdOut, &defaultBufferInfo ); + #else + #endif +} + +rsTerminal::~rsTerminal() +{ + #ifdef _WIN32 + CloseHandle( hStdOut ); + #endif +} + +void rsTerminal::ClearTerminal() +{ + #ifdef _WIN32 + system( "cls" ); //i'm lazy + #else + printf( "\033[2J" ); + #endif +} + +void rsTerminal::SetCursorPosition( rsCOORD_t pos ) +{ + #ifdef _WIN32 + COORD position = { pos.x, pos.y }; + SetConsoleCursorPosition( hStdOut, position ); + #else + //POSIX terminal is indexed from 1 + //and oriented other way + printf( "\033[%d;%dH", pos.y + 1, pos.x + 1 ); + #endif +} + +void rsTerminal::SetTextColour( int terminalColour ) +{ + #ifdef _WIN32 + if ( COLOUR_DEFAULT == terminalColour ) { + SetConsoleTextAttribute( hStdOut, defaultBufferInfo.wAttributes & 7 ); + return; + } + int winColour = 0; + if ( COLOUR_BLUE & terminalColour ) { winColour |= FOREGROUND_BLUE; } + if ( COLOUR_GREEN & terminalColour ) { winColour |= FOREGROUND_GREEN; } + if ( COLOUR_RED & terminalColour ) { winColour |= FOREGROUND_RED; } + if ( COLOUR_WHITE & terminalColour ) { winColour |= FOREGROUND_INTENSITY; } + SetConsoleTextAttribute( hStdOut, winColour ); + #else + if ( COLOUR_DEFAULT == terminalColour ) { + printf( "\033[39m" ); + return; + } + int colourOffset = 0; + if ( COLOUR_RED & terminalColour ) { colourOffset |= 1; } + if ( COLOUR_GREEN & terminalColour ) { colourOffset |= 2; } + if ( COLOUR_BLUE & terminalColour ) { colourOffset |= 4; } + printf( "\033[3%dm", colourOffset); + #endif +} + +void rsTerminal::SetToDefault() +{ + #ifdef _WIN32 + SetConsoleTextAttribute( hStdOut, defaultBufferInfo.wAttributes ); + #else + printf( "\033[39m\033[49m" ); + #endif +} + +void rsTerminal::HideCursor() +{ + #ifdef _WIN32 + CONSOLE_CURSOR_INFO cursor; + cursor.bVisible = false; + SetConsoleCursorInfo( hStdOut, &cursor ); + #else + printf( "\033[?25l" ); + #endif +} + +void rsTerminal::ShowCursor() +{ + #ifdef _WIN32 + CONSOLE_CURSOR_INFO cursor; + cursor.bVisible = true; + SetConsoleCursorInfo( hStdOut, &cursor ); + #else + printf( "\033[?25h" ); + #endif +} + diff --git a/work/.gitignore b/work/.gitignore new file mode 100644 index 0000000..7ff134a --- /dev/null +++ b/work/.gitignore @@ -0,0 +1,3 @@ +#Ignore this directory except this file +* +!.gitignore