Initial commit
This commit is contained in:
@@ -0,0 +1 @@
|
||||
space-walk
|
||||
@@ -0,0 +1,74 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "board.h"
|
||||
#include "spaceship.h"
|
||||
|
||||
Board::Board() {
|
||||
// Reserve 0 SpaceShips of memory for each planet
|
||||
for (unsigned char i = 0; i < BOARD_SIZE; i++) {
|
||||
this->planets[i] = new std::vector<SpaceShip *>(0);
|
||||
}
|
||||
}
|
||||
|
||||
Board::~Board() {
|
||||
for (auto planet : this->planets) {
|
||||
delete planet;
|
||||
}
|
||||
}
|
||||
|
||||
SpaceShip *Board::getShip(unsigned char planet, unsigned char pos) {
|
||||
if (planet >= BOARD_SIZE || pos >= this->planets[planet]->size()) {
|
||||
return new SpaceShip;
|
||||
}
|
||||
|
||||
return this->planets[planet]->at(pos);
|
||||
}
|
||||
|
||||
std::vector<SpaceShip *> *Board::getShips(unsigned char planet) {
|
||||
if (planet >= BOARD_SIZE) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return this->planets[planet];
|
||||
}
|
||||
|
||||
bool Board::setShip(unsigned char planet, SpaceShip *ship) {
|
||||
if (planet >= BOARD_SIZE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Insert if the ship doesn't already exist on a planet
|
||||
if (ship->getPlanet() == PLANET_UNSET) {
|
||||
ship->setPlanet(planet);
|
||||
this->planets[planet]->push_back(ship);
|
||||
this->sortPlanet(planet);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Board::moveShip(unsigned char planet, SpaceShip *ship) {
|
||||
char shipPlanet = ship->getPlanet();
|
||||
if (planet >= BOARD_SIZE || shipPlanet == -1 || shipPlanet == planet) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto tmp = this->planets[(unsigned char)shipPlanet];
|
||||
// Move ship to the end of the vector and then erase the last element
|
||||
// (Erase-remove idiom)
|
||||
tmp->erase(std::remove(tmp->begin(), tmp->end(), ship), tmp->end());
|
||||
|
||||
ship->setPlanet(planet);
|
||||
this->planets[planet]->push_back(ship);
|
||||
this->sortPlanet(planet);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Board::sortPlanet(unsigned char planet) {
|
||||
// Sort all ships on the planet, using function/functor/lambda
|
||||
std::sort(this->planets[planet]->begin(), this->planets[planet]->end(),
|
||||
[](SpaceShip *s1, SpaceShip *s2) -> bool {
|
||||
return s1->getSize() > s2->getSize();
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef BOARD_H
|
||||
#define BOARD_H
|
||||
|
||||
#define BOARD_SIZE 14
|
||||
|
||||
#include <vector>
|
||||
|
||||
class SpaceShip;
|
||||
|
||||
class Board
|
||||
{
|
||||
public:
|
||||
Board();
|
||||
~Board();
|
||||
|
||||
SpaceShip *getShip(unsigned char planet, unsigned char pos);
|
||||
std::vector<SpaceShip *> *getShips(unsigned char planet);
|
||||
bool setShip(unsigned char planet, SpaceShip *ship);
|
||||
bool moveShip(unsigned char planet, SpaceShip *ship);
|
||||
void sortPlanet(unsigned char planet);
|
||||
|
||||
private:
|
||||
// Data layout:
|
||||
// Black hole, 6 planets, 6 planets, black hole
|
||||
std::vector<SpaceShip *> *planets[BOARD_SIZE];
|
||||
};
|
||||
|
||||
#endif // BOARD_H
|
||||
@@ -0,0 +1,84 @@
|
||||
#include "board.h"
|
||||
#include "boardwindow.h"
|
||||
#include "maingame.h"
|
||||
#include "spaceship.h"
|
||||
|
||||
BoardWindow::BoardWindow(int height, int width, Board *board) :
|
||||
height(height),
|
||||
width(width),
|
||||
board(board) {
|
||||
}
|
||||
|
||||
BoardWindow::~BoardWindow() {
|
||||
}
|
||||
|
||||
void BoardWindow::update() {
|
||||
Window::update();
|
||||
this->resize();
|
||||
|
||||
int twoThirds = (this->getRows() / 3) * 2;
|
||||
int halfCols = this->getCols() / 2;
|
||||
int y = (twoThirds / 2) - 12;
|
||||
int x = halfCols - 4 - 1;
|
||||
// Print black hole
|
||||
this->printBlackHole(y, x, 0);
|
||||
|
||||
y += 6;
|
||||
x = (this->getCols() / 2) - (46 / 2) - 1;
|
||||
// Print all planets
|
||||
for (int i = 1; i < BOARD_SIZE - 1; i++) {
|
||||
this->printPlanet(y, x, i);
|
||||
x += 8;
|
||||
|
||||
if (i == (BOARD_SIZE - 2) / 2) {
|
||||
x = (this->getCols() / 2) - (46 / 2) - 1;
|
||||
y += 6;
|
||||
}
|
||||
}
|
||||
|
||||
y += 6;
|
||||
x = halfCols - 4 - 1;
|
||||
// Print black hole
|
||||
this->printBlackHole(y, x, BOARD_SIZE - 1);
|
||||
}
|
||||
|
||||
void BoardWindow::resize() {
|
||||
int rows = this->getMaxRows() - this->height;
|
||||
int cols = this->getMaxCols() - this->width;
|
||||
this->setWindow(rows, cols, 0, 0);
|
||||
Window::resize();
|
||||
}
|
||||
|
||||
void BoardWindow::printBlackHole(int y, int x, int planet) {
|
||||
this->print("+------+", y, x);
|
||||
this->print("| |", y + 1, x);
|
||||
this->print("| |", y + 2, x);
|
||||
this->print("| |", y + 3, x);
|
||||
this->print("+------+", y + 4, x);
|
||||
|
||||
this->printSpaceShip(y + 1, x + 1, planet, 6);
|
||||
}
|
||||
|
||||
void BoardWindow::printPlanet(int y, int x, int planet) {
|
||||
this->print("+----+", y, x);
|
||||
this->print("| |", y + 1, x);
|
||||
this->print("| |", y + 2, x);
|
||||
this->print("| |", y + 3, x);
|
||||
this->print("+----+", y + 4, x);
|
||||
|
||||
this->printSpaceShip(y + 1, x + 1, planet, 4);
|
||||
}
|
||||
|
||||
void BoardWindow::printSpaceShip(int y, int x, int planet, int width) {
|
||||
auto tmp = this->board->getShips(planet);
|
||||
int size = (int)tmp->size() + 1;
|
||||
for (int i = 1; i < size; i++) {
|
||||
tmp->at(i - 1)->render(this, y, x, false);
|
||||
x++;
|
||||
|
||||
if (i != 1 && i % width == 0) {
|
||||
y++;
|
||||
x -= width;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef BOARDWINDOW_H
|
||||
#define BOARDWINDOW_H
|
||||
|
||||
#include "window.h"
|
||||
|
||||
class Board;
|
||||
|
||||
class BoardWindow : public Window
|
||||
{
|
||||
public:
|
||||
BoardWindow(int height, int width, Board *board);
|
||||
~BoardWindow();
|
||||
|
||||
void update();
|
||||
void resize();
|
||||
void printBlackHole(int y, int x, int planet);
|
||||
void printPlanet(int y, int x, int planet);
|
||||
void printSpaceShip(int y, int x, int planet, int width);
|
||||
|
||||
private:
|
||||
int height;
|
||||
int width;
|
||||
Board *board;
|
||||
};
|
||||
|
||||
#endif // BOARDWINDOW_H
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
#ifndef GAMESTATE
|
||||
#define GAMESTATE
|
||||
|
||||
#include <chrono> // time
|
||||
#include <thread> // sleep_for
|
||||
|
||||
#include "inputoutput.h"
|
||||
#include "window.h"
|
||||
|
||||
class GameState
|
||||
{
|
||||
public:
|
||||
// Makes sure that the inherited class's destructor is called
|
||||
virtual ~GameState() {}
|
||||
|
||||
virtual void initialize() {}
|
||||
virtual void update() {}
|
||||
virtual void render() {}
|
||||
virtual void destroy() {}
|
||||
|
||||
static void sleep(int amount) {
|
||||
// Sleep for amount ms
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(amount));
|
||||
}
|
||||
};
|
||||
|
||||
class GameStateManager
|
||||
{
|
||||
public:
|
||||
GameStateManager() : state(nullptr) {
|
||||
Window::initialize();
|
||||
}
|
||||
|
||||
~GameStateManager() {
|
||||
if(this->state != nullptr) {
|
||||
this->state->destroy();
|
||||
delete this->state;
|
||||
}
|
||||
|
||||
Window::destroy();
|
||||
}
|
||||
|
||||
void setState(GameState* state) {
|
||||
if(this->state != nullptr) {
|
||||
this->state->destroy();
|
||||
delete this->state;
|
||||
}
|
||||
|
||||
this->state = state;
|
||||
if(this->state != nullptr) {
|
||||
this->state->initialize();
|
||||
}
|
||||
}
|
||||
|
||||
void update() {
|
||||
GameState::sleep(15);
|
||||
|
||||
if(this->state != nullptr) {
|
||||
this->state->update();
|
||||
}
|
||||
}
|
||||
|
||||
void render() {
|
||||
if(this->state != nullptr) {
|
||||
this->state->render();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
GameState *state;
|
||||
};
|
||||
|
||||
extern GameStateManager gameStateManager;
|
||||
|
||||
#endif // GAMESTATE
|
||||
@@ -0,0 +1,47 @@
|
||||
#include "infowindow.h"
|
||||
#include "maingame.h"
|
||||
#include "player.h"
|
||||
#include "spaceship.h"
|
||||
|
||||
InfoWindow::InfoWindow(int height, int width, Player **player, SpaceShip **ship) :
|
||||
height(height),
|
||||
width(width),
|
||||
player(player),
|
||||
ship(ship) {
|
||||
}
|
||||
|
||||
InfoWindow::~InfoWindow() {
|
||||
}
|
||||
|
||||
void InfoWindow::update() {
|
||||
Window::update();
|
||||
this->resize();
|
||||
|
||||
int y = 0;
|
||||
int x = 1;
|
||||
for (unsigned char i = 0; i < PLAYER_SIZE; i++) {
|
||||
this->player[i]->render(this, y, x, i + 1);
|
||||
y += 6;
|
||||
|
||||
int shipIdx = i * SHIP_SIZE / 2;
|
||||
for (unsigned char j = shipIdx; j < shipIdx + SHIP_SIZE / 2; j++) {
|
||||
this->ship[j]->render(this, y, x);
|
||||
x++;
|
||||
|
||||
if (x > 3) {
|
||||
y++;
|
||||
x = 1;
|
||||
}
|
||||
}
|
||||
|
||||
y += 2;
|
||||
}
|
||||
}
|
||||
|
||||
void InfoWindow::resize() {
|
||||
int rows = this->getMaxRows() - this->height;
|
||||
int x = this->getMaxCols() - this->width;
|
||||
int cols = this->getMaxCols() - x;
|
||||
this->setWindow(rows, cols, 0, x);
|
||||
Window::resize();
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef INFOWINDOW_H
|
||||
#define INFOWINDOW_H
|
||||
|
||||
#include "window.h"
|
||||
|
||||
class Player;
|
||||
class SpaceShip;
|
||||
|
||||
class InfoWindow : public Window
|
||||
{
|
||||
public:
|
||||
InfoWindow(int height, int width, Player **player, SpaceShip **ship);
|
||||
~InfoWindow();
|
||||
|
||||
void update();
|
||||
void resize();
|
||||
|
||||
private:
|
||||
int height;
|
||||
int width;
|
||||
Player **player;
|
||||
SpaceShip **ship;
|
||||
};
|
||||
|
||||
#endif // INFOWINDOW_H
|
||||
@@ -0,0 +1,69 @@
|
||||
#include <cstdio> // size_t
|
||||
#include <ncurses.h>
|
||||
|
||||
#include "inputoutput.h"
|
||||
|
||||
void IO::initialize() {
|
||||
}
|
||||
|
||||
void IO::update() {
|
||||
IO::keyCode = getch();
|
||||
|
||||
if (keyCode == KEY_ESC) {
|
||||
IO::setQuit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::string IO::trim(std::string str) {
|
||||
size_t first = str.find_first_not_of(" ");
|
||||
if (first == std::string::npos) {
|
||||
return "";
|
||||
}
|
||||
size_t last = str.find_last_not_of(" ");
|
||||
return str.substr(first, (last - first + 1));
|
||||
}
|
||||
|
||||
std::string IO::untrim(std::string str, unsigned int length) {
|
||||
unsigned int strLength = str.length();
|
||||
if (length > strLength) {
|
||||
int halfDiff = (length - strLength) / 2;
|
||||
|
||||
std::string tmpStr;
|
||||
for (int i = 0; i < halfDiff; i++) {
|
||||
tmpStr += " ";
|
||||
}
|
||||
|
||||
str.insert(0, tmpStr);
|
||||
str.append(tmpStr);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
int IO::getKeyCode() {
|
||||
return IO::keyCode;
|
||||
}
|
||||
|
||||
std::string IO::getKeyName() {
|
||||
return std::string(keyname(IO::keyCode));
|
||||
}
|
||||
|
||||
std::string IO::getStrInput() {
|
||||
echo();
|
||||
char *tmp = new char();
|
||||
getstr(tmp);
|
||||
noecho();
|
||||
return std::string(tmp);
|
||||
}
|
||||
|
||||
bool IO::getQuit() {
|
||||
return IO::quit;
|
||||
}
|
||||
|
||||
void IO::setQuit() {
|
||||
IO::quit = true;
|
||||
}
|
||||
|
||||
int IO::keyCode = ERR;
|
||||
bool IO::quit = false;
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef INPUTOUTPUT_H
|
||||
#define INPUTOUTPUT_H
|
||||
|
||||
#define KEY_ESC 27
|
||||
#define KEY_SPACE 32
|
||||
|
||||
#include <string>
|
||||
|
||||
class IO
|
||||
{
|
||||
public:
|
||||
static void initialize();
|
||||
static void update();
|
||||
|
||||
static std::string trim(std::string str);
|
||||
static std::string untrim(std::string str, unsigned int length);
|
||||
|
||||
static int getKeyCode();
|
||||
static std::string getKeyName();
|
||||
static std::string getStrInput();
|
||||
static bool getQuit();
|
||||
static void setQuit();
|
||||
|
||||
private:
|
||||
static int keyCode;
|
||||
static bool quit;
|
||||
};
|
||||
|
||||
#endif // INPUTOUTPUT_H
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Rick van Vonderen
|
||||
* 0945444
|
||||
* TI2B
|
||||
*
|
||||
* Avoid repeated writing by using:
|
||||
* - functions with parameters (no globals) instead of almost identical pieces of code
|
||||
* - repetitive loops and arrays instead of identical activities
|
||||
* - constants instead of identical values
|
||||
*
|
||||
* Divide your program into modules and/or classes that:
|
||||
* - have an explicit, well-defined interface
|
||||
* - be as independent as possible
|
||||
* - to be developed and tested separately
|
||||
*
|
||||
* Make your code understandable for others by using:
|
||||
* - Clear names in camel case, only start class names with a capital letter, consistently indent
|
||||
* - Clear, concise commentary, only where this adds something
|
||||
* - Standard terminology from the customer's field or application
|
||||
*
|
||||
* ClassExample
|
||||
* variableExample
|
||||
* DEFINE_EXAMPLE
|
||||
*/
|
||||
|
||||
#include <cstring> // strcmp()
|
||||
#include <ncurses.h> // refresh()
|
||||
|
||||
#include "gamestate.h"
|
||||
#include "inputoutput.h"
|
||||
#include "mainmenu.h"
|
||||
#include "test.h"
|
||||
|
||||
GameStateManager gameStateManager;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
#ifdef DEBUG
|
||||
// IO::print("DEBUG MODE ENABLED");
|
||||
refresh();
|
||||
GameState::sleep(1000);
|
||||
|
||||
if (argc >= 2 && strcmp(argv[1], "-t") == 0) {
|
||||
Test();
|
||||
}
|
||||
#endif
|
||||
|
||||
gameStateManager.setState(new MainMenu());
|
||||
|
||||
while (!IO::getQuit()) {
|
||||
gameStateManager.render();
|
||||
gameStateManager.update();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
+338
@@ -0,0 +1,338 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "board.h"
|
||||
#include "boardwindow.h"
|
||||
#include "inputoutput.h"
|
||||
#include "maingame.h"
|
||||
#include "mainmenu.h"
|
||||
#include "messagebox.h"
|
||||
#include "player.h"
|
||||
#include "selectionbox.h"
|
||||
#include "spaceship.h"
|
||||
#include "window.h"
|
||||
#include "infowindow.h"
|
||||
|
||||
MainGame::MainGame(Player **player) :
|
||||
help("Phase 1!\n\nThe players take turns, placing a spaceship on a planet\nof their choice."),
|
||||
phase(false),
|
||||
playerTurn(0),
|
||||
queuePlanet(-1),
|
||||
player(player),
|
||||
board(nullptr),
|
||||
ship(nullptr),
|
||||
boardWindow(nullptr),
|
||||
infoWindow(nullptr) {
|
||||
// Reserve 0 spaceships of memory for the queue
|
||||
this->queue = new std::vector<SpaceShip *>(0);
|
||||
}
|
||||
|
||||
void MainGame::initialize() {
|
||||
this->board = new Board();
|
||||
|
||||
this->ship = new SpaceShip*[SHIP_SIZE] { nullptr };
|
||||
unsigned char cCounter = 0;
|
||||
unsigned char colors[PLAYER_SIZE] = { PAIR_RED_BLACK, PAIR_BLUE_BLACK };
|
||||
unsigned char sCounter = 0;
|
||||
unsigned char sizes[3] = { SpaceShip::SMALL, SpaceShip::MEDIUM, SpaceShip::BIG };
|
||||
// Create 9 ships for each player, 3 of each size
|
||||
for (unsigned char i = 0; i < SHIP_SIZE; i++) {
|
||||
if (i != 0 && i % (SHIP_SIZE / PLAYER_SIZE) == 0) {
|
||||
cCounter++;
|
||||
}
|
||||
|
||||
if (i != 0 && i % 3 == 0) {
|
||||
sCounter++;
|
||||
}
|
||||
|
||||
if (sCounter >= 3) {
|
||||
sCounter = 0;
|
||||
}
|
||||
|
||||
this->ship[i] = new SpaceShip(colors[cCounter], sizes[sCounter]);
|
||||
}
|
||||
|
||||
this->boardWindow = new BoardWindow(0, 16, this->board);
|
||||
this->infoWindow = new InfoWindow(0, 16, this->player, this->ship);
|
||||
|
||||
// Display help message
|
||||
MainGame::render();
|
||||
MessageBox(this->help);
|
||||
}
|
||||
|
||||
void MainGame::update() {
|
||||
MainGame::sleep(250);
|
||||
|
||||
// Display new help message on phase change
|
||||
if (this->changePhase) {
|
||||
this->phase = true;
|
||||
this->changePhase = false;
|
||||
|
||||
this->help = "Phase 2!\n\nThe players take turns, evacuating a planet of their choice.";
|
||||
MessageBox(this->help);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this->phase) {
|
||||
this->phase1();
|
||||
}
|
||||
else {
|
||||
this->phase2();
|
||||
}
|
||||
}
|
||||
|
||||
void MainGame::render() {
|
||||
this->boardWindow->clear();
|
||||
this->infoWindow->clear();
|
||||
|
||||
this->boardWindow->update();
|
||||
this->infoWindow->update();
|
||||
|
||||
this->boardWindow->render();
|
||||
this->infoWindow->render();
|
||||
}
|
||||
|
||||
void MainGame::destroy() {
|
||||
delete this->board;
|
||||
delete this->boardWindow;
|
||||
delete this->infoWindow;
|
||||
|
||||
for (int i = 0; i < SHIP_SIZE; i++) {
|
||||
delete this->ship[i];
|
||||
}
|
||||
delete []this->ship;
|
||||
|
||||
for (int i = 0; i < PLAYER_SIZE; i++) {
|
||||
delete this->player[i];
|
||||
}
|
||||
delete []this->player;
|
||||
}
|
||||
|
||||
void MainGame::phase1() {
|
||||
std::string playerTurnStr = std::to_string(this->playerTurn + 1);
|
||||
SelectionBox s = SelectionBox(0, 16);
|
||||
|
||||
// Ask the current player to pick a Spaceship size
|
||||
std::string sizeStr = "Player " + playerTurnStr + ", pick a spaceship size.";
|
||||
std::string sizeOptions[] = {"S", "M", "B", "\0"};
|
||||
unsigned char sizeSelection = s.select(sizeStr, &sizeOptions[0]);
|
||||
|
||||
// Ask the current player to pick a planet
|
||||
std::string planetStr = "Player " + playerTurnStr + ", pick a planet to put this spaceship on.";
|
||||
std::string planetOptions[] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "\0"};
|
||||
unsigned char planetSelection = s.select(planetStr, &planetOptions[0]);
|
||||
|
||||
// Calculate array index
|
||||
int startLoop = SHIP_SIZE / PLAYER_SIZE * this->playerTurn + (sizeSelection * 3);
|
||||
// Get ships of player selected planet
|
||||
auto ships = this->board->getShips(std::stoi(planetOptions[planetSelection]));
|
||||
|
||||
bool placedShip = false;
|
||||
bool shouldExit;
|
||||
// Check all 3 ships of the size the player selected
|
||||
for (int i = startLoop; i < startLoop + 3; i++) {
|
||||
shouldExit = false;
|
||||
|
||||
// Check if spaceship is already on a planet
|
||||
if (this->ship[i]->getPlanet() != PLANET_UNSET) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If planet already holds spaceship of equal size
|
||||
for(auto ship : *ships) {
|
||||
if (this->ship[i]->getSize() == ship->getSize()) {
|
||||
shouldExit = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldExit) {
|
||||
MessageBox("You cant place spaceships of the same size on a planet during this phase!", "Error");
|
||||
break;
|
||||
}
|
||||
|
||||
// Add spaceship to planet
|
||||
this->board->setShip(std::stoi(planetOptions[planetSelection]), this->ship[i]);
|
||||
this->nextPlayerTurn();
|
||||
placedShip = true;
|
||||
break;
|
||||
}
|
||||
if (!placedShip && !shouldExit) {
|
||||
MessageBox("Please select a size of which you still have unplaced spaceships!", "Error");
|
||||
}
|
||||
|
||||
// Check if all ships have been placed
|
||||
bool allPlaced = true;
|
||||
for (int i = 0; i < SHIP_SIZE; i++) {
|
||||
if (this->ship[i]->getPlanet() == PLANET_UNSET) {
|
||||
allPlaced = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (allPlaced) {
|
||||
this->changePhase = true;
|
||||
}
|
||||
}
|
||||
|
||||
void MainGame::phase2() {
|
||||
std::string playerTurnStr = std::to_string(this->playerTurn + 1);
|
||||
SelectionBox s = SelectionBox(0, 16);
|
||||
|
||||
// Move next spaceship in the queue
|
||||
if (this->queue->size() > 0) {
|
||||
// Determine the middle of the board
|
||||
unsigned char halfBoard = (BOARD_SIZE - 2) / 2; // 6
|
||||
|
||||
// Planet rotation order, where |x| is a black hole
|
||||
// 1 ... 6 -> |13| -> 12 ... 7 -> |0| -> 1
|
||||
|
||||
// 0 .. 5
|
||||
if (this->queuePlanet < halfBoard) {
|
||||
this->queuePlanet++;
|
||||
}
|
||||
// 8 .. 13
|
||||
else if (this->queuePlanet > halfBoard + 1) {
|
||||
this->queuePlanet--;
|
||||
}
|
||||
// 6
|
||||
else if (this->queuePlanet == halfBoard) {
|
||||
this->queuePlanet = BOARD_SIZE - 1;
|
||||
}
|
||||
// 7
|
||||
else if (this->queuePlanet == halfBoard + 1) {
|
||||
this->queuePlanet = 0;
|
||||
}
|
||||
|
||||
unsigned char shipSelection = 0;
|
||||
// If the the current and next ship are of the same size, ask which goes first
|
||||
if (this->queue->size() > 1) {
|
||||
SpaceShip *tmpShip = this->queue->at(0);
|
||||
SpaceShip *tmpShip2 = this->queue->at(1);
|
||||
if (tmpShip->getSize() == tmpShip2->getSize() &&
|
||||
tmpShip->getColor() != tmpShip2->getColor()) {
|
||||
std::string shipStr = "Player " + playerTurnStr + ", pick the next ship that will evacuate.";
|
||||
std::string shipOptions[] = {"Yours", "Theirs", "\0"};
|
||||
shipSelection = s.select(shipStr, &shipOptions[0]);
|
||||
}
|
||||
}
|
||||
|
||||
board->moveShip(this->queuePlanet, this->queue->at(shipSelection));
|
||||
return;
|
||||
}
|
||||
else if (this->queuePlanet != -1) {
|
||||
this->queuePlanet = -1;
|
||||
this->nextPlayerTurn();
|
||||
this->calculateWinner();
|
||||
return;
|
||||
}
|
||||
|
||||
// Ask the current player if they want to skip their turn
|
||||
unsigned char playerChip = this->player[this->playerTurn]->getChip();
|
||||
if (playerChip > 0) {
|
||||
std::string skipStr = "Player " + playerTurnStr + ", do you want to skip your turn for 1 chip?";
|
||||
std::string skipOptions[] = {"No", "Yes", "\0"};
|
||||
unsigned char skipSelection = s.select(skipStr, &skipOptions[0]);
|
||||
|
||||
if (skipOptions[skipSelection] == "Yes") {
|
||||
this->player[this->playerTurn]->setChip(playerChip - 1);
|
||||
this->nextPlayerTurn();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Ask the current player to pick a planet
|
||||
std::string planetStr = "Player " + playerTurnStr + ", pick a planet to evacuate.";
|
||||
std::string planetOptions[] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "\0"};
|
||||
unsigned char planetSelection = s.select(planetStr, &planetOptions[0]);
|
||||
|
||||
// Get ships of player selected planet
|
||||
auto ships = this->board->getShips(std::stoi(planetOptions[planetSelection]));
|
||||
|
||||
// Check if the selected planet holds a spaceship of the current player,
|
||||
// using function/functor/lambda
|
||||
unsigned char playerColor = this->player[(int)this->playerTurn]->getColor();
|
||||
auto findShip = std::find_if(ships->begin(), ships->end(),
|
||||
[playerColor](SpaceShip *ship) {return ship->getColor() == playerColor; });
|
||||
|
||||
// If so, add this planet to the queue
|
||||
if (findShip != ships->end()) {
|
||||
this->queue = ships;
|
||||
this->queuePlanet = this->queue->at(0)->getPlanet();
|
||||
}
|
||||
else {
|
||||
MessageBox("Please select a planet that holds a ship of your own!", "Error");
|
||||
}
|
||||
}
|
||||
|
||||
void MainGame::nextPlayerTurn() {
|
||||
this->playerTurn++;
|
||||
if (this->playerTurn > PLAYER_SIZE - 1) {
|
||||
this->playerTurn = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void MainGame::calculateWinner() {
|
||||
// Get all ships from the black holes
|
||||
auto blackHole1 = this->board->getShips(0);
|
||||
auto blackHole2 = this->board->getShips(BOARD_SIZE - 1);
|
||||
|
||||
int totalScore = CHIP_AMOUNT * CHIP_SCORE +
|
||||
3 * SpaceShip::BIG +
|
||||
3 * SpaceShip::MEDIUM +
|
||||
3 * SpaceShip::SMALL;
|
||||
|
||||
// Fill players possible total score
|
||||
int score[PLAYER_SIZE];
|
||||
std::fill_n(score, PLAYER_SIZE, totalScore);
|
||||
|
||||
// Calculate players score
|
||||
int crashedShips;
|
||||
bool gameOver = false;
|
||||
for (int i = 0; i < PLAYER_SIZE; i++) {
|
||||
|
||||
// Subtract all used chips from the total score
|
||||
score[i] -= (CHIP_AMOUNT - this->player[i]->getChip()) * CHIP_SCORE;
|
||||
|
||||
crashedShips = 0;
|
||||
for (auto ship : *blackHole1) {
|
||||
if (this->player[i]->getColor() == ship->getColor()) {
|
||||
crashedShips++;
|
||||
|
||||
// Subtract crashed ship from the total score
|
||||
score[i] -= ship->getSize();
|
||||
}
|
||||
}
|
||||
for (auto ship : *blackHole2) {
|
||||
if (this->player[i]->getColor() == ship->getColor()) {
|
||||
crashedShips++;
|
||||
|
||||
// Subtract crashed ship from the total score
|
||||
score[i] -= ship->getSize();
|
||||
}
|
||||
}
|
||||
|
||||
// If a player has run out of ships..
|
||||
if (crashedShips == SHIP_SIZE / PLAYER_SIZE) {
|
||||
gameOver = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Print victory screen
|
||||
if (gameOver) {
|
||||
std::string printStr;
|
||||
|
||||
int winnerIdx = 0;
|
||||
for (int i = 0; i < PLAYER_SIZE; i++) {
|
||||
printStr += "Player " + std::to_string(i + 1) + ": scored " +
|
||||
std::to_string(score[i]) + " points.\n";
|
||||
|
||||
if (i < PLAYER_SIZE - 1 && score[i] < score[i + 1]) {
|
||||
winnerIdx = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
printStr.insert(0, this->player[winnerIdx]->getName() + " has won!\n\n");
|
||||
MessageBox(printStr, "Victory");
|
||||
|
||||
gameStateManager.setState(new MainMenu());
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
#ifndef MAINGAME_H
|
||||
#define MAINGAME_H
|
||||
|
||||
// Each player holds 9 ships, 3 of each size
|
||||
#define SHIP_SIZE 18
|
||||
#define PLAYER_SIZE 2
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "gamestate.h"
|
||||
|
||||
class Board;
|
||||
class BoardWindow;
|
||||
class InfoWindow;
|
||||
class Player;
|
||||
class SpaceShip;
|
||||
|
||||
class MainGame : public GameState
|
||||
{
|
||||
public:
|
||||
MainGame(Player **player);
|
||||
|
||||
void initialize();
|
||||
void update();
|
||||
void render();
|
||||
void destroy();
|
||||
|
||||
private:
|
||||
void phase1();
|
||||
void phase2();
|
||||
void nextPlayerTurn();
|
||||
void calculateWinner();
|
||||
|
||||
std::string help;
|
||||
bool phase;
|
||||
bool changePhase;
|
||||
unsigned char playerTurn;
|
||||
|
||||
char queuePlanet;
|
||||
std::vector<SpaceShip *> *queue;
|
||||
|
||||
Player **player;
|
||||
Board *board;
|
||||
SpaceShip **ship;
|
||||
BoardWindow *boardWindow;
|
||||
InfoWindow *infoWindow;
|
||||
};
|
||||
|
||||
#endif // MAINGAME_H
|
||||
@@ -0,0 +1,98 @@
|
||||
#include "inputoutput.h"
|
||||
#include "maingame.h"
|
||||
#include "mainmenu.h"
|
||||
#include "player.h"
|
||||
#include "window.h"
|
||||
|
||||
void MainMenu::initialize() {
|
||||
int rows;
|
||||
int cols;
|
||||
Window::getMaXYZ(stdscr, rows, cols);
|
||||
|
||||
this->window = new Window(rows, cols, 0, 0);
|
||||
this->titleScreen = true;
|
||||
this->player = new Player*[PLAYER_SIZE] { nullptr };
|
||||
}
|
||||
|
||||
void MainMenu::update() {
|
||||
if (this->titleScreen) {
|
||||
IO::update();
|
||||
|
||||
if (IO::getKeyName() == " ") {
|
||||
this->titleScreen = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int y;
|
||||
int x;
|
||||
std::string tmpStr;
|
||||
unsigned char colors[PLAYER_SIZE] = { PAIR_RED_BLACK, PAIR_BLUE_BLACK };
|
||||
for (int i = 0; i < PLAYER_SIZE; i++) {
|
||||
if (this->player[i] == nullptr) {
|
||||
this->window->getYX(y, x);
|
||||
|
||||
tmpStr = "";
|
||||
while (tmpStr == "") {
|
||||
tmpStr = IO::trim(this->window->getStr());
|
||||
this->window->setYX(y, x);
|
||||
}
|
||||
|
||||
this->player[i] = new Player();
|
||||
this->player[i]->setName(tmpStr);
|
||||
this->player[i]->setColor(colors[i]);
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == PLAYER_SIZE - 1) {
|
||||
gameStateManager.setState(new MainGame(this->player));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainMenu::render() {
|
||||
this->window->clear();
|
||||
|
||||
this->window->update();
|
||||
this->window->setWindow(this->window->getMaxRows(), this->window->getMaxCols(), 0, 0);
|
||||
this->window->resize();
|
||||
|
||||
if (this->titleScreen) {
|
||||
this->window->printSide("", "Rick van Vonderen");
|
||||
this->window->setYX(1, 0);
|
||||
this->window->printSide("", "0945444");
|
||||
this->window->setYX(2, 0);
|
||||
this->window->printSide("", "TI2B");
|
||||
|
||||
this->window->setYX(this->window->getRows() / 2 - 1, 0);
|
||||
this->window->printCenter("--- Space Walk ---");
|
||||
|
||||
this->window->setYX(this->window->getRows() - 4, 0);
|
||||
this->window->printCenter("Press <Space> to walk..");
|
||||
}
|
||||
else {
|
||||
int x = this->window->getCols() / 2 - 11 ;
|
||||
int y = this->window->getRows() / 2;
|
||||
std::string tmp;
|
||||
for (int i = 0; i < PLAYER_SIZE; i++) {
|
||||
tmp = std::string("Enter Player ") + std::to_string(i + 1) + std::string(" name: ");
|
||||
|
||||
if (this->player[i] != nullptr) {
|
||||
tmp += this->player[i]->getName();
|
||||
}
|
||||
|
||||
this->window->print(tmp, y, x);
|
||||
y++;
|
||||
|
||||
if (this->player[i] == nullptr) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this->window->render();
|
||||
}
|
||||
|
||||
void MainMenu::destroy() {
|
||||
delete this->window;
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
#ifndef MAINMENU_H
|
||||
#define MAINMENU_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "gamestate.h"
|
||||
|
||||
class Player;
|
||||
class Window;
|
||||
|
||||
class MainMenu : public GameState
|
||||
{
|
||||
public:
|
||||
void initialize();
|
||||
void update();
|
||||
void render();
|
||||
void destroy();
|
||||
|
||||
private:
|
||||
bool titleScreen;
|
||||
Window *window;
|
||||
Player **player;
|
||||
};
|
||||
|
||||
#endif // MAINMENU_H
|
||||
@@ -0,0 +1,54 @@
|
||||
#------------------------------------------------------------------------------#
|
||||
|
||||
PROGRAM := "space-walk"
|
||||
HEADERS := \
|
||||
board.h \
|
||||
boardwindow.h \
|
||||
gamestate.h \
|
||||
infowindow.h \
|
||||
inputoutput.h \
|
||||
maingame.h \
|
||||
mainmenu.h \
|
||||
messagebox.h \
|
||||
player.h \
|
||||
selectionbox.h \
|
||||
spaceship.h \
|
||||
test.h \
|
||||
window.h
|
||||
SOURCES := \
|
||||
board.cpp \
|
||||
boardwindow.cpp \
|
||||
infowindow.cpp \
|
||||
inputoutput.cpp \
|
||||
main.cpp \
|
||||
maingame.cpp \
|
||||
mainmenu.cpp \
|
||||
messagebox.cpp \
|
||||
player.cpp \
|
||||
selectionbox.cpp \
|
||||
spaceship.cpp \
|
||||
test.cpp \
|
||||
window.cpp
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
|
||||
CXX := g++
|
||||
CXXFLAGS := -lncurses -std=c++11 -Wall -Wextra
|
||||
|
||||
.PHONY: all debug run clean
|
||||
|
||||
all: run
|
||||
|
||||
debug: CXXFLAGS += -g -DDEBUG
|
||||
debug: run
|
||||
|
||||
run: compile
|
||||
@./$(PROGRAM) ; \
|
||||
stty sane
|
||||
|
||||
compile: ${HEADERS} ${SOURCES}
|
||||
$(CXX) $(CXXFLAGS) $? -o $(PROGRAM)
|
||||
|
||||
clean:
|
||||
@-echo "Cleaning project.." ; \
|
||||
rm -f $(PROGRAM)
|
||||
@@ -0,0 +1,57 @@
|
||||
#include <ncurses.h> // A_REVERSE
|
||||
#include <sstream> // istringstream
|
||||
#include <vector>
|
||||
|
||||
#include "inputoutput.h"
|
||||
#include "messagebox.h"
|
||||
|
||||
MessageBox::MessageBox(std::string message) :
|
||||
MessageBox(message, "") {
|
||||
}
|
||||
|
||||
MessageBox::MessageBox(std::string message, std::string title) {
|
||||
// Split message on newline
|
||||
std::vector<std::string> lines;
|
||||
std::istringstream strStream(message);
|
||||
std::string tmpStr;
|
||||
while (std::getline(strStream, tmpStr, '\n')) {
|
||||
lines.push_back(tmpStr);
|
||||
}
|
||||
|
||||
int rows;
|
||||
int cols;
|
||||
Window::getMaXYZ(stdscr, rows, cols);
|
||||
|
||||
// Calculate window dimension and size
|
||||
int winRows = lines.size() + 8;
|
||||
int winCols = cols * 0.9;
|
||||
int y = (rows - winRows) / 2;
|
||||
int x = (cols - winCols) / 2;
|
||||
this->setWindow(winRows, winCols, y, x);
|
||||
|
||||
// Print title
|
||||
title = IO::untrim(!title.empty() ? title : "Message", winCols - 2);
|
||||
this->print(title, 0, 0, A_REVERSE);
|
||||
|
||||
// Print the message line by line
|
||||
y = (winRows - lines.size()) / 2 - 1;
|
||||
for (auto l : lines) {
|
||||
this->setYX(y, 0);
|
||||
this->printCenter(l);
|
||||
y++;
|
||||
}
|
||||
|
||||
this->setYX(winRows - 3, 0);
|
||||
this->printCenter("Press <Space> to continue ",
|
||||
COLOR_PAIR(PAIR_GRAY_BLACK_BRIGHT));
|
||||
|
||||
this->render();
|
||||
|
||||
// Press space to continue
|
||||
while(!IO::getQuit()) {
|
||||
IO::update();
|
||||
if (IO::getKeyName() == " ") {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef MESSAGEBOX_H
|
||||
#define MESSAGEBOX_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "window.h"
|
||||
|
||||
class MessageBox : public Window
|
||||
{
|
||||
public:
|
||||
MessageBox(std::string message);
|
||||
MessageBox(std::string message, std::string title);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif // MESSAGEBOX_H
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
#include <ncurses.h> // A_REVERSE
|
||||
#include <stdio.h>
|
||||
|
||||
#include "player.h"
|
||||
#include "infowindow.h"
|
||||
|
||||
Player::Player() :
|
||||
chip(CHIP_AMOUNT),
|
||||
name("") {
|
||||
}
|
||||
|
||||
void Player::render(InfoWindow *window, int y, int x, unsigned char number) {
|
||||
std::string print;
|
||||
print += " Player ";
|
||||
print += std::to_string(number);
|
||||
print += " ";
|
||||
window->print(print, y, x - 1, A_REVERSE);
|
||||
y += 2;
|
||||
|
||||
window->print(this->name, y, x, COLOR_PAIR(this->color));
|
||||
y += 2;
|
||||
|
||||
for (unsigned char i = 0; i < this->chip; i++) {
|
||||
window->print("C", y, x, COLOR_PAIR(PAIR_WHITE_BLACK));
|
||||
x++;
|
||||
window->print(" ", y, x);
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char Player::getChip() {
|
||||
return this->chip;
|
||||
}
|
||||
|
||||
void Player::setChip(unsigned char chip) {
|
||||
this->chip = chip;
|
||||
}
|
||||
|
||||
unsigned char Player::getColor() {
|
||||
return this->color;
|
||||
}
|
||||
|
||||
void Player::setColor(unsigned char color) {
|
||||
this->color = color;
|
||||
}
|
||||
|
||||
std::string Player::getName() {
|
||||
return this->name;
|
||||
}
|
||||
|
||||
void Player::setName(std::string name) {
|
||||
this->name = name;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef PLAYER_H
|
||||
#define PLAYER_H
|
||||
|
||||
#define CHIP_AMOUNT 4
|
||||
#define CHIP_SCORE 2
|
||||
|
||||
#include <string>
|
||||
|
||||
class InfoWindow;
|
||||
|
||||
class Player
|
||||
{
|
||||
public:
|
||||
Player();
|
||||
|
||||
void render(InfoWindow *window, int y, int x, unsigned char number);
|
||||
|
||||
unsigned char getChip();
|
||||
void setChip(unsigned char chip);
|
||||
unsigned char getColor();
|
||||
void setColor(unsigned char color);
|
||||
std::string getName();
|
||||
void setName(std::string name);
|
||||
|
||||
private:
|
||||
unsigned char chip;
|
||||
unsigned char color;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
#endif // PLAYER_H
|
||||
@@ -0,0 +1,88 @@
|
||||
#include <cstring> // strlen
|
||||
#include <sstream> // istringstream
|
||||
|
||||
#include "inputoutput.h"
|
||||
#include "selectionbox.h"
|
||||
|
||||
SelectionBox::SelectionBox(int height, int width) :
|
||||
height(height),
|
||||
width(width) {
|
||||
this->update();
|
||||
}
|
||||
|
||||
void SelectionBox::update() {
|
||||
Window::update();
|
||||
this->resize();
|
||||
}
|
||||
|
||||
void SelectionBox::resize() {
|
||||
int rows = (this->getMaxRows() - this->height) / 4;
|
||||
int cols = this->getMaxCols() - this->width;
|
||||
this->setWindow(rows, cols, this->getMaxRows() - rows, 0);
|
||||
Window::resize();
|
||||
}
|
||||
|
||||
unsigned char SelectionBox::select(std::string str, std::string *selection) {
|
||||
int amount = 0;
|
||||
while (!selection[amount].empty()) {
|
||||
amount++;
|
||||
}
|
||||
|
||||
std::string tmpStr;
|
||||
int tmpInt;
|
||||
// Display options and get user input
|
||||
while(!IO::getQuit()) {
|
||||
this->clear();
|
||||
this->update();
|
||||
this->printSelection(str, selection);
|
||||
this->render();
|
||||
|
||||
tmpStr = IO::trim(this->getStr());
|
||||
if (tmpStr == "") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (this->isNumber(tmpStr)) {
|
||||
tmpInt = std::stoi(tmpStr);
|
||||
if (tmpInt > 0 && tmpInt < amount + 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (unsigned char)tmpInt - 1;
|
||||
}
|
||||
|
||||
void SelectionBox::printSelection(std::string str, std::string *selection) {
|
||||
int y = 0;
|
||||
|
||||
// Split and print message on newline
|
||||
std::istringstream strStream(str);
|
||||
std::string tmpStr;
|
||||
while (std::getline(strStream, tmpStr, '\n')) {
|
||||
this->print(tmpStr, y, 1);
|
||||
y++;
|
||||
}
|
||||
y++;
|
||||
|
||||
int amount = 0;
|
||||
while (!selection[amount].empty()) {
|
||||
if (amount < 6) {
|
||||
this->print("- " + selection[amount], y, 1);
|
||||
}
|
||||
else {
|
||||
this->print("- " + selection[amount], y - 6, 10);
|
||||
}
|
||||
|
||||
y++;
|
||||
amount++;
|
||||
}
|
||||
|
||||
this->print("Select option number: ", this->getRows() - 3, 1);
|
||||
}
|
||||
|
||||
bool SelectionBox::isNumber(const std::string &s) {
|
||||
std::string::const_iterator it = s.begin();
|
||||
while (it != s.end() && std::isdigit(*it)) it++;
|
||||
return !s.empty() && it == s.end();
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef SELECTIONBOX_H
|
||||
#define SELECTIONBOX_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "window.h"
|
||||
|
||||
class SelectionBox : public Window
|
||||
{
|
||||
public:
|
||||
SelectionBox(int height, int width);
|
||||
|
||||
void update();
|
||||
void resize();
|
||||
|
||||
unsigned char select(std::string str, std::string *selection);
|
||||
void printSelection(std::string str, std::string *selection);
|
||||
|
||||
private:
|
||||
bool isNumber(const std::string &s);
|
||||
|
||||
int height;
|
||||
int width;
|
||||
};
|
||||
|
||||
#endif // SELECTIONBOX_H
|
||||
@@ -0,0 +1,57 @@
|
||||
#include "spaceship.h"
|
||||
#include "window.h"
|
||||
|
||||
SpaceShip::SpaceShip() :
|
||||
color(COLOR_UNSET),
|
||||
size(SpaceShip::SIZE_UNSET),
|
||||
planet(PLANET_UNSET) {
|
||||
}
|
||||
|
||||
SpaceShip::SpaceShip(unsigned char color, unsigned char size) :
|
||||
color(color),
|
||||
size(size),
|
||||
planet(PLANET_UNSET) {
|
||||
}
|
||||
|
||||
void SpaceShip::render(Window *window, int y, int x, bool checkPlaced) {
|
||||
if (checkPlaced && this->planet != PLANET_UNSET) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string print = "";
|
||||
if (this->size == SpaceShip::SMALL) {
|
||||
print = "S";
|
||||
}
|
||||
else if (this->size == SpaceShip::MEDIUM) {
|
||||
print = "M";
|
||||
}
|
||||
else if (this->size == SpaceShip::BIG) {
|
||||
print = "B";
|
||||
}
|
||||
|
||||
window->print(print, y, x, COLOR_PAIR(this->color));
|
||||
}
|
||||
|
||||
unsigned char SpaceShip::getColor() {
|
||||
return this->color;
|
||||
}
|
||||
|
||||
void SpaceShip::setColor(unsigned char color) {
|
||||
this->color = color;
|
||||
}
|
||||
|
||||
unsigned char SpaceShip::getSize() {
|
||||
return this->size;
|
||||
}
|
||||
|
||||
void SpaceShip::setSize(unsigned char size) {
|
||||
this->size = size;
|
||||
}
|
||||
|
||||
char SpaceShip::getPlanet() {
|
||||
return this->planet;
|
||||
}
|
||||
|
||||
void SpaceShip::setPlanet(char planet) {
|
||||
this->planet = planet;
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
#ifndef SPACESHIP_H
|
||||
#define SPACESHIP_H
|
||||
|
||||
#define PLANET_UNSET -1
|
||||
|
||||
class Window;
|
||||
|
||||
class SpaceShip
|
||||
{
|
||||
public:
|
||||
SpaceShip();
|
||||
SpaceShip(unsigned char color, unsigned char size);
|
||||
|
||||
void render(Window *window, int y, int x, bool checkPlaced = true);
|
||||
|
||||
unsigned char getColor();
|
||||
void setColor(unsigned char color);
|
||||
unsigned char getSize();
|
||||
void setSize(unsigned char size);
|
||||
char getPlanet();
|
||||
void setPlanet(char planet);
|
||||
|
||||
enum Size {
|
||||
SIZE_UNSET = 0,
|
||||
SMALL = 1,
|
||||
MEDIUM = 3,
|
||||
BIG = 4,
|
||||
};
|
||||
|
||||
private:
|
||||
unsigned char color;
|
||||
unsigned char size;
|
||||
char planet;
|
||||
};
|
||||
|
||||
#endif // SPACESHIP_H
|
||||
@@ -0,0 +1,68 @@
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <ncurses.h>
|
||||
|
||||
#include "board.h"
|
||||
#include "inputoutput.h"
|
||||
#include "maingame.h"
|
||||
#include "player.h"
|
||||
#include "spaceship.h"
|
||||
#include "test.h"
|
||||
|
||||
Test::Test() {
|
||||
|
||||
// IO::print("Unit test\n");
|
||||
refresh();
|
||||
|
||||
// Board tests
|
||||
Board *board = new Board;
|
||||
|
||||
char arrayShip[3] = { SpaceShip::SMALL, SpaceShip::MEDIUM, SpaceShip::BIG };
|
||||
SpaceShip *ship = new SpaceShip(1, arrayShip[0]);
|
||||
SpaceShip *ship2 = new SpaceShip(1, arrayShip[1]);
|
||||
SpaceShip *ship3 = new SpaceShip(1, arrayShip[2]);
|
||||
board->setShip(0, ship);
|
||||
board->setShip(0, ship);
|
||||
board->setShip(1, ship);
|
||||
board->setShip(1, ship2);
|
||||
board->setShip(2, ship3);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
auto ships = board->getShips(i);
|
||||
// printf("%lu\n", ships->size());
|
||||
for (int j = 0; j < (int)ships->size(); j++) {
|
||||
// printf("%d\n", ships->at(j)->getSize());
|
||||
assert(ships->at(j)->getSize() == arrayShip[i]);
|
||||
}
|
||||
assert(ships->size() == 1);
|
||||
}
|
||||
board->moveShip(3, ship3);
|
||||
assert(board->getShip(3, 0)->getSize() == arrayShip[2]);
|
||||
|
||||
// char array[SHIP_SIZE] = {
|
||||
// SpaceShip::SMALL, SpaceShip::SMALL, SpaceShip::SMALL,
|
||||
// SpaceShip::MEDIUM, SpaceShip::MEDIUM, SpaceShip::MEDIUM,
|
||||
// SpaceShip::BIG, SpaceShip::BIG, SpaceShip::BIG,
|
||||
// SpaceShip::SMALL, SpaceShip::SMALL, SpaceShip::SMALL,
|
||||
// SpaceShip::MEDIUM, SpaceShip::MEDIUM, SpaceShip::MEDIUM,
|
||||
// SpaceShip::BIG, SpaceShip::BIG, SpaceShip::BIG,
|
||||
// };
|
||||
// for (unsigned char i = 0; i < SHIP_SIZE; i++) {
|
||||
// // printf("%d\n", board.ships[i]->getSize());
|
||||
// // printf("%d\n", array[i]);
|
||||
// assert(board.ships[i]->getSize() == array[i]);
|
||||
// }
|
||||
|
||||
// IO::print("Passed board checks..");
|
||||
refresh();
|
||||
|
||||
getch();
|
||||
|
||||
// Cleanup resources
|
||||
delete board;
|
||||
delete ship;
|
||||
delete ship2;
|
||||
delete ship3;
|
||||
|
||||
IO::setQuit();
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#ifndef TEST_H
|
||||
#define TEST_H
|
||||
|
||||
class Test
|
||||
{
|
||||
public:
|
||||
Test();
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif // TEST_H
|
||||
+222
@@ -0,0 +1,222 @@
|
||||
#include <cstdio>
|
||||
|
||||
#include "gamestate.h"
|
||||
#include "window.h"
|
||||
|
||||
Window::Window(int rows, int cols, int y, int x) :
|
||||
rows(rows),
|
||||
cols(cols),
|
||||
y(0),
|
||||
x(0),
|
||||
window(newwin(rows, cols, y, x)) {
|
||||
}
|
||||
|
||||
Window::~Window() {
|
||||
delwin(this->window);
|
||||
}
|
||||
|
||||
void Window::initialize() {
|
||||
// Start curses mode
|
||||
initscr();
|
||||
// Disable line buffering
|
||||
cbreak();
|
||||
// Enable reading of function keys
|
||||
keypad(stdscr, TRUE);
|
||||
// Dont echo while reading input
|
||||
noecho();
|
||||
// Disable cursor visibility
|
||||
curs_set(0);
|
||||
|
||||
// If terminal supports colors
|
||||
if(!has_colors()) {
|
||||
printw("Your terminal does not support color\n");
|
||||
}
|
||||
else {
|
||||
start_color();
|
||||
use_default_colors();
|
||||
|
||||
init_pair(PAIR_WHITE_BLACK, COLOR_WHITE, COLOR_BLACK);
|
||||
init_pair(PAIR_WHITE_BRIGHT_BLACK, COLOR_WHITE_BRIGHT, COLOR_BLACK);
|
||||
init_pair(PAIR_RED_BLACK, COLOR_RED, COLOR_BLACK);
|
||||
init_pair(PAIR_BLUE_BLACK, COLOR_BLUE, COLOR_BLACK);
|
||||
init_pair(PAIR_GRAY_BLACK_BRIGHT, COLOR_GRAY, COLOR_BLACK_BRIGHT);
|
||||
}
|
||||
|
||||
// Add bright colors, intensity range: 0-1000
|
||||
if(!can_change_color()) {
|
||||
printw("Your terminal does not support changing colors\n");
|
||||
}
|
||||
else {
|
||||
init_color(COLOR_BLACK, 0, 0, 0);
|
||||
init_color(COLOR_WHITE, 680, 680, 680);
|
||||
init_color(COLOR_GRAY, 380, 380, 380);
|
||||
|
||||
init_color(COLOR_BLACK_BRIGHT, 110, 110, 110); // 0, 0, 0
|
||||
init_color(COLOR_RED_BRIGHT, 900, 0, 0); // 680, 0, 0
|
||||
init_color(COLOR_GREEN_BRIGHT, 0, 900, 0); // 0, 680, 0
|
||||
init_color(COLOR_YELLOW_BRIGHT, 900, 900, 0); // 680, 680, 0
|
||||
init_color(COLOR_BLUE_BRIGHT, 0, 0, 900); // 0, 0, 680
|
||||
init_color(COLOR_MAGENTA_BRIGHT, 900, 0, 900); // 680, 0, 680
|
||||
init_color(COLOR_CYAN_BRIGHT, 0, 900, 900); // 0, 680, 680
|
||||
init_color(COLOR_WHITE_BRIGHT, 900, 900, 900); // 680, 680, 680
|
||||
}
|
||||
}
|
||||
|
||||
void Window::update() {
|
||||
Window::getMaXYZ(stdscr, this->maxRows, this->maxCols);
|
||||
}
|
||||
|
||||
void Window::render() {
|
||||
box(this->window, 0, 0);
|
||||
wrefresh(this->window);
|
||||
}
|
||||
|
||||
void Window::destroy() {
|
||||
// Restore line buffering
|
||||
nocbreak();
|
||||
// Restore cursor
|
||||
curs_set(1);
|
||||
// End curses mode
|
||||
endwin();
|
||||
}
|
||||
|
||||
void Window::clear() {
|
||||
this->setYX(0, 0);
|
||||
|
||||
// Set background color
|
||||
// wbkgdset(this->window, COLOR_PAIR(3));
|
||||
|
||||
// Copy blanks to every position in the window, clearing the screen
|
||||
werase(this->window);
|
||||
}
|
||||
|
||||
void Window::resize() {
|
||||
wresize(this->window, this->rows, this->cols);
|
||||
mvwin(this->window, this->y, this->x);
|
||||
}
|
||||
|
||||
void Window::print(std::string str, char newLine) {
|
||||
this->print(str, this->y, this->x);
|
||||
this->x += str.length();
|
||||
if (newLine == 1) {
|
||||
this->x = 0;
|
||||
this->y++;
|
||||
}
|
||||
}
|
||||
|
||||
void Window::print(std::string str, int y, int x) {
|
||||
this->y = y;
|
||||
this->x = x;
|
||||
mvwprintw(this->window, y + 1, x + 1, str.c_str());
|
||||
}
|
||||
|
||||
void Window::print(std::string str, int y, int x, int attribute) {
|
||||
wattron(this->window, attribute);
|
||||
this->print(str, y, x);
|
||||
wattroff(this->window, attribute);
|
||||
}
|
||||
|
||||
void Window::printCenter(std::string str) {
|
||||
int halfBoard = this->cols / 2;
|
||||
int halfStr = str.length() / 2;
|
||||
this->print(str, this->y, halfBoard - halfStr - 1);
|
||||
}
|
||||
|
||||
void Window::printCenter(std::string str, int attribute) {
|
||||
wattron(this->window, attribute);
|
||||
this->printCenter(str);
|
||||
wattroff(this->window, attribute);
|
||||
}
|
||||
|
||||
void Window::printSide(std::string left, std::string right) {
|
||||
this->print(left, this->y, 1);
|
||||
this->print(right, this->y, this->cols - right.length() - 3);
|
||||
}
|
||||
|
||||
void Window::getYX(int &y, int &x) {
|
||||
getyx(this->window, y, x);
|
||||
}
|
||||
|
||||
void Window::setYX(int y, int x) {
|
||||
this->y = y;
|
||||
this->x = x;
|
||||
wmove(this->window, y, x);
|
||||
}
|
||||
|
||||
void Window::getMaXYZ(int &rows, int &cols) {
|
||||
getmaxyx(this->window, rows, cols);
|
||||
}
|
||||
|
||||
void Window::getMaXYZ(WINDOW *window, int &rows, int &cols) {
|
||||
getmaxyx(window, rows, cols);
|
||||
}
|
||||
|
||||
std::string Window::getStr() {
|
||||
curs_set(1);
|
||||
echo();
|
||||
char *tmp = new char();
|
||||
wgetstr(this->window, tmp);
|
||||
noecho();
|
||||
curs_set(0);
|
||||
return std::string(tmp);
|
||||
}
|
||||
|
||||
int Window::getMaxRows() {
|
||||
return this->maxRows;
|
||||
}
|
||||
|
||||
int Window::getMaxCols() {
|
||||
return this->maxCols;
|
||||
}
|
||||
|
||||
int Window::getRows() {
|
||||
return this->rows;
|
||||
}
|
||||
|
||||
void Window::setRows(int rows) {
|
||||
this->rows = rows;
|
||||
}
|
||||
|
||||
int Window::getCols() {
|
||||
return this->cols;
|
||||
}
|
||||
|
||||
void Window::setCols(int cols) {
|
||||
this->cols = cols;
|
||||
}
|
||||
|
||||
int Window::getY() {
|
||||
return this->y;
|
||||
}
|
||||
|
||||
void Window::setY(int y) {
|
||||
this->y = y;
|
||||
}
|
||||
|
||||
int Window::getX() {
|
||||
return this->x;
|
||||
}
|
||||
|
||||
void Window::setX(int x) {
|
||||
this->x = x;
|
||||
}
|
||||
|
||||
void Window::setWindow(int rows, int cols, int y, int x) {
|
||||
this->setRows(rows);
|
||||
this->setCols(cols);
|
||||
this->setY(y);
|
||||
this->setX(x);
|
||||
if (this->window == nullptr) {
|
||||
this->window = newwin(rows, cols, y, x);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
Window::Window() :
|
||||
rows(0),
|
||||
cols(0),
|
||||
y(0),
|
||||
x(0),
|
||||
window(nullptr) {
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
#ifndef WINDOW_H
|
||||
#define WINDOW_H
|
||||
|
||||
#define COLOR_UNSET 0
|
||||
#define COLOR_BLACK_BRIGHT 8
|
||||
#define COLOR_RED_BRIGHT 9
|
||||
#define COLOR_GREEN_BRIGHT 10
|
||||
#define COLOR_YELLOW_BRIGHT 11
|
||||
#define COLOR_BLUE_BRIGHT 12
|
||||
#define COLOR_MAGENTA_BRIGHT 13
|
||||
#define COLOR_CYAN_BRIGHT 14
|
||||
#define COLOR_WHITE_BRIGHT 15
|
||||
#define COLOR_GRAY 16
|
||||
|
||||
#define PAIR_WHITE_BLACK 1
|
||||
#define PAIR_WHITE_BRIGHT_BLACK 2
|
||||
#define PAIR_RED_BLACK 3
|
||||
#define PAIR_BLUE_BLACK 4
|
||||
#define PAIR_GRAY_BLACK_BRIGHT 5
|
||||
|
||||
#include <ncurses.h>
|
||||
#include <string>
|
||||
|
||||
class Window
|
||||
{
|
||||
public:
|
||||
Window(int rows, int cols, int y, int x);
|
||||
~Window();
|
||||
|
||||
static void initialize();
|
||||
void update();
|
||||
void render();
|
||||
static void destroy();
|
||||
void clear();
|
||||
void resize();
|
||||
|
||||
void print(std::string str, char newLine = 1);
|
||||
void print(std::string str, int y, int x);
|
||||
void print(std::string str, int y, int x, int attribute);
|
||||
void printCenter(std::string str);
|
||||
void printCenter(std::string str, int attribute);
|
||||
void printSide(std::string left, std::string right);
|
||||
|
||||
void getYX(int &y, int &x);
|
||||
void setYX(int y, int x);
|
||||
void getMaXYZ(int &rows, int &cols);
|
||||
static void getMaXYZ(WINDOW *window, int &rows, int &cols);
|
||||
std::string getStr();
|
||||
|
||||
int getMaxRows();
|
||||
int getMaxCols();
|
||||
int getRows();
|
||||
void setRows(int rows);
|
||||
int getCols();
|
||||
void setCols(int cols);
|
||||
int getY();
|
||||
void setY(int y);
|
||||
int getX();
|
||||
void setX(int x);
|
||||
void setWindow(int rows, int cols, int y, int x);
|
||||
|
||||
protected:
|
||||
Window();
|
||||
|
||||
private:
|
||||
int maxRows;
|
||||
int maxCols;
|
||||
int rows;
|
||||
int cols;
|
||||
int y;
|
||||
int x;
|
||||
WINDOW *window;
|
||||
};
|
||||
|
||||
#endif // WINDOW_H
|
||||
Reference in New Issue
Block a user