Skip to content

Commit

Permalink
move code from the original repository and add a README file
Browse files Browse the repository at this point in the history
  • Loading branch information
eerio committed Aug 3, 2023
0 parents commit 2d6bb17
Show file tree
Hide file tree
Showing 11 changed files with 1,736 additions and 0 deletions.
17 changes: 17 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
cmake_minimum_required(VERSION 3.1)

project(MIMUW_SIK_BOMBERMAN)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wconversion -O2 -Werror")

find_package(Boost 1.74.0 COMPONENTS program_options system)
find_package(Threads)

include_directories(include)

add_executable(robots-client robots-client.cpp)
target_link_libraries(robots-client Boost::program_options Boost::system Threads::Threads)

add_executable(robots-server robots-server.cpp)
target_link_libraries(robots-server Boost::program_options Boost::system Threads::Threads)
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# A bomberman implementation
59 changes: 59 additions & 0 deletions common.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#ifndef BOMBERMAN_COMMON_HPP
#define BOMBERMAN_COMMON_HPP

#include <charconv> // std::from_chars
#include <concepts> // std::unsigned_integral
#include <stdexcept> // std::runtime_error
#include <system_error> // std::errc

#include <boost/asio.hpp>

#include "streamable-buffer.hpp"

// The maximal size of data in a UDP packet is the maximal size of an UDP
// packet (1 << 16 bytes) decreased by the size of an IP header (20 bytes)
// and an UDP header (8 bytes).
constexpr size_t MAX_UDP_MESSAGE_SIZE = (1 << 16) - 20 - 8;

using port_t = uint16_t;

class invalid_number : public std::runtime_error {
using std::runtime_error::runtime_error;
};

// Parse unsigned, base-10 integral from the given C string.
// Throw invalid_number on any non-standardiness such as a leading sign.
template <std::unsigned_integral T>
T parse_uint(const char* first, const char* last) {
T result;
std::from_chars_result conv = std::from_chars(
first,
last,
result
);

if (conv.ec != std::errc {}) {
throw invalid_number("Invalid format for an unsigned integer");
}

return result;
}

// to nie powinno byc w cpp - to powinno byc jako template z tcp/udp

void send(streamable_buffer& stream, boost::asio::ip::tcp::socket& sock) {
auto buffer = stream.get_buffer();
const std::vector<unsigned char>& data { buffer.begin(), buffer.end() };
sock.send(boost::asio::buffer(data));
stream.clear();
}

std::vector<uint8_t> read(boost::asio::ip::tcp::socket& sock, size_t n) {
std::vector<uint8_t> buffer (n);
size_t rec = boost::asio::read(sock, boost::asio::buffer(buffer));
assert(rec == n);
return buffer;
}

#endif // BOMBERMAN_COMMON_HPP

96 changes: 96 additions & 0 deletions debug.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/** This file contains debugging helpers for the project.
* Most notably, it contains std::ostream operator<< overloads for most
* common types such as selected STL containers and this projects'
* message formats for the client-server-gui communication.
*/

#ifndef BOMBERMAN_DEBUG_HPP
#define BOMBERMAN_DEBUG_HPP

#include <deque>
#include <iostream>
#include <map>
#include <utility>
#include <vector>

#include "streamable-buffer.hpp"
#include "messages.hpp"

template<typename u, typename v>
std::ostream& operator<< (std::ostream& out, const std::pair<u, v>& x) {
out << '<' << x.first << ", " << x.second << '>';
return out;
}

template<typename u>
std::ostream& operator<< (std::ostream& out, const std::vector<u>& x) {
out << '[';
if (x.size() > 0) {
for (size_t i=0; i < x.size() - 1; ++i) { out << x[i] << ", "; }
out << x[x.size() - 1];
}
out << ']';
return out;
}

template<typename u>
std::ostream& operator<< (std::ostream& out, const std::deque<u>& x) {
out << '[';
if (x.size() > 0) {
for (size_t i=0; i < x.size() - 1; ++i) { out << x[i] << ", "; }
out << x[x.size() - 1];
}
out << ']';
return out;
}

template<typename u, typename v>
std::ostream& operator<< (std::ostream& out, const std::map<u, v>& x) {
out << '[';
if (x.size() > 0) {
for (auto it=x.begin(); it != prev(x.end()); ++it) {
out << *it << ", ";
}
out << *std::prev(x.end());
}
out << ']';
return out;
}

std::ostream& operator<<(std::ostream& os, const streamable_buffer& s) {
os << s.buffer;
return os;
}

std::ostream& operator<<(std::ostream& os, const Position& pos) {
return os << std::make_pair(pos.x, pos.y);
}

std::ostream& operator<<(std::ostream& os, const Bomb& bomb) {
return os << std::make_pair(bomb.position, bomb.timer);
}

std::ostream& operator<< (std::ostream& os, const Player& player) {
return os << std::make_pair(player.name, player.address);
}

template<typename T, typename ... Args>
void print(T t, Args ... args) {
std::cout << t;
((std::cout << ' ' << args), ...);
}

template<typename ... Args>
void println([[maybe_unused]]Args ... args) {
print(args...);
print('\n');
}

template<typename ... Args>
void debug([[maybe_unused]]Args ... args) {
#ifndef NDEBUG
println(args...);
#endif
}

#endif // BOMBERMAN_DEBUG_HPP
206 changes: 206 additions & 0 deletions messages.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
/* This file contains definitions of types and message formats used through-
* out the project in communication between client, server and GUI server.
* The order of members of the structs below and the order of these types
* in related std::variants is important:
* -the order of members determines the order in which they will be
* serialized.
* -the order of types corresponds directly to the message ids which they
* will be assigned
* Name of the 'msg_id' member is not to be changed - objects are tested
* for presence of such a member in the serialization code
*/

#ifndef BOMBERMAN_MESSAGES_HPP
#define BOMBERMAN_MESSAGES_HPP

#include <cstdint> // uint8_t, ...
#include <string>
#include <vector>
#include <map>
#include <variant>

// Definitions of the most primitive types ---------------------------------
using bomb_id_t = uint32_t;
using bomb_timer_t = uint16_t;
// we could use an enum, but this is just more convenient for serialization
using direction_t = uint8_t;
using explosion_radius_t = uint16_t;
using game_length_t = uint16_t;
using initial_blocks_t = uint16_t;
using msg_id_t = uint8_t;
using player_id_t = uint8_t;
using players_count_t = uint8_t;
using pos_t = uint16_t;
using score_t = uint32_t;
using server_name_t = std::string;
using strlen_t = uint8_t;
using turn_duration_t = uint64_t;
using turn_t = uint16_t;

struct Position {
pos_t x;
pos_t y;
auto operator<=>(const Position&) const = default;
};

struct Bomb {
Position position;
bomb_timer_t timer;
};

struct Player {
std::string name;
std::string address;
};

// Definitions of events ---------------------------------------------------
struct EventBombPlaced {
static constexpr uint8_t msg_id = 0;
bomb_id_t bomb_id;
Position position;
};

struct EventBombExploded {
static constexpr uint8_t msg_id = 1;
bomb_id_t bomb_id;
std::vector<player_id_t> robots_destroyed;
std::vector<Position> blocks_destroyed;
};

struct EventPlayerMoved {
static constexpr uint8_t msg_id = 2;
player_id_t player_id;
Position position;
};

struct EventBlockPlaced {
static constexpr uint8_t msg_id = 3;
Position position;
};

using Event = std::variant<
EventBombPlaced,
EventBombExploded,
EventPlayerMoved,
EventBlockPlaced
>;

// Definitions of messages from client to server ---------------------------
struct ClientMessageJoin {
static constexpr uint8_t msg_id = 0;
std::string name;
};

struct ClientMessagePlaceBomb {
static constexpr uint8_t msg_id = 1;
};

struct ClientMessagePlaceBlock {
static constexpr uint8_t msg_id = 2;
};

struct ClientMessageMove {
static constexpr uint8_t msg_id = 3;
direction_t direction;
};

using ClientMessage = std::variant<
ClientMessageJoin,
ClientMessagePlaceBomb,
ClientMessagePlaceBlock,
ClientMessageMove
>;

// Definitions of messages from server to client ---------------------------
struct ServerMessageHello {
static constexpr uint8_t msg_id = 0;
std::string server_name;
players_count_t players_count;
pos_t size_x;
pos_t size_y;
game_length_t game_length;
explosion_radius_t explosion_radius;
bomb_timer_t bomb_timer;
};

struct ServerMessageAcceptedPlayer {
static constexpr uint8_t msg_id = 1;
player_id_t player_id;
Player player;
};

struct ServerMessageGameStarted {
static constexpr uint8_t msg_id = 2;
std::map<player_id_t, Player> players;
};

struct ServerMessageTurn {
static constexpr uint8_t msg_id = 3;
game_length_t turn;
std::vector<Event> events;
};

struct ServerMessageGameEnded {
static constexpr uint8_t msg_id = 4;
std::map<player_id_t, score_t> scores;
};

using ServerMessage = std::variant<
ServerMessageHello,
ServerMessageAcceptedPlayer,
ServerMessageGameStarted,
ServerMessageTurn,
ServerMessageGameEnded
>;

// Definitions of messages from client to GUI server -----------------------
struct DrawMessageLobby {
static constexpr uint8_t msg_id = 0;
std::string server_name;
players_count_t players_count;
pos_t size_x;
pos_t size_y;
game_length_t game_length;
explosion_radius_t explosion_radius;
bomb_timer_t bomb_timer;
std::map<player_id_t, Player> players;
};

struct DrawMessageGame {
static constexpr uint8_t msg_id = 1;
std::string server_name;
pos_t size_x;
pos_t size_y;
game_length_t game_length;
turn_t turn;
std::map<player_id_t, Player> players;
std::map<player_id_t, Position> player_positions;
std::vector<Position> blocks;
std::vector<Bomb> bombs;
std::vector<Position> explosions;
std::map<player_id_t, score_t> scores;
};

using DrawMessage = std::variant<DrawMessageLobby, DrawMessageGame>;

// Definitions of messages from GUI server to client -----------------------
struct InputMessagePlaceBomb {
static constexpr uint8_t msg_id = 0;
};

struct InputMessagePlaceBlock {
static constexpr uint8_t msg_id = 1;
};

struct InputMessageMove {
static constexpr uint8_t msg_id = 2;
direction_t direction;
};

using InputMessage = std::variant<
InputMessagePlaceBomb,
InputMessagePlaceBlock,
InputMessageMove
>;

#endif // BOMBERMAN_MESSAGES_HPP
Loading

0 comments on commit 2d6bb17

Please sign in to comment.