-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathClientState.h
161 lines (143 loc) · 4.31 KB
/
ClientState.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#ifndef SIK_ZAD3_CLIENTSTATE_H
#define SIK_ZAD3_CLIENTSTATE_H
#include <boost/program_options.hpp>
#include <iostream>
#include <map>
#include <set>
#include <string>
#include "MessageUtils.h"
namespace po = boost::program_options;
/**
* Struct created for the sole purpose of parsing and saving
* command line options.
* If help is used, all other options are optional (we won't run).
* If no help is detected, all of the other options are required.
*/
struct ClientCommandLineOpts {
std::string display_address;
std::string player_name;
uint16_t port;
std::string server_address;
bool parse_command_line(int argc, char *argv[]) {
try {
po::options_description desc("Opcje programu:");
desc.add_options()
("gui-address,d", po::value<std::string>(&display_address)->required(),
"<(nazwa hosta):(port) lub (IPv4):(port) lub (IPv6):(port)>")
("help,h", "Wypisuje jak używać programu")
("player-name,n", po::value<std::string>(&player_name)->required(),
"<String>")
("port,p", po::value<uint16_t>(&port)->required(),"<u16>")
("server-address,s",po::value<std::string>(&server_address)->required(),
"<(nazwa hosta):(port) lub (IPv4):(port) lub (IPv6):(port)>");
po::variables_map vm;
po::store(po::parse_command_line(argc, argv, desc), vm);
if (vm.count("help")) {
std::cout << desc << "\n";
return false;
}
po::notify(vm);
} catch (std::exception &e) {
std::cerr << "Error: " << e.what() << "\n";
return false;
} catch (...) {
std::cerr << "Unknown error!"
<< "\n";
return false;
}
return true;
}
};
/**
* Struct for storing ClientState.
* At all times there will only be one ClientState (for one Client).
* It will never be used polymorphically nor will it have subclasses.
* It's main function is to just store data, that's why I chose struct over
* class.
*/
struct ClientState {
std::string server_name;
uint8_t players_count;
uint16_t size_x;
uint16_t size_y;
uint16_t game_length;
uint16_t explosion_radius;
uint16_t bomb_timer;
std::map<PlayerId, Player> players;
uint16_t turn;
std::map<PlayerId, Position> positions;
std::set<Position> blocks;
std::map<BombId, Bomb> bombs;
std::set<Position> explosions;
std::map<PlayerId, Score> scores;
std::set<PlayerId> would_die;
std::set<Position> blocks_to_destroy;
bool game_on = false;
/**
* Ease function to add new bomb (we have the bomb timer ready)
*/
void add_bomb(BombId id, Position pos) {
bombs[id] = {pos, bomb_timer};
}
/**
* Function that calculates current round's explosions.
* It goes explosion_radius - 1 times to all 4 sides, unless it
* finds a block, then it will be the last explosion position in that
* direction.
* If a bomb exploded on a block, we only insert one explosion - on that
* blocks position.
*/
void calculate_explosions(Position explosion) {
explosions.insert(explosion);
if (blocks.contains(explosion)) {
return;
}
for (uint16_t i = 1; i < explosion_radius + 1 && explosion.y + i < size_y;
++i) {
Position temp(explosion.x, explosion.y + i);
explosions.insert(temp);
if (blocks.contains(temp)) {
break;
}
}
for (uint16_t i = 1; i < explosion_radius + 1 && explosion.y - i >= 0;
++i) {
Position temp(explosion.x, explosion.y - i);
explosions.insert(temp);
if (blocks.contains(temp)) {
break;
}
}
for (uint16_t i = 1; i < explosion_radius + 1 && explosion.x + i < size_x;
++i) {
Position temp(explosion.x + i, explosion.y);
explosions.insert(temp);
if (blocks.contains(temp)) {
break;
}
}
for (uint16_t i = 1; i < explosion_radius + 1 && explosion.x - i >= 0;
++i) {
Position temp(explosion.x - i, explosion.y);
explosions.insert(temp);
if (blocks.contains(temp)) {
break;
}
}
}
/**
* Prepares the clientstate for a new game (on the same server).
*/
void reset() {
players.clear();
turn = 0;
positions.clear();
blocks.clear();
bombs.clear();
explosions.clear();
scores.clear();
would_die.clear();
game_on = false;
}
};
#endif // SIK_ZAD3_CLIENTSTATE_H