diff --git a/03_monopoly/board.cpp b/03_monopoly/board.cpp new file mode 100644 index 0000000..2fcb3a9 --- /dev/null +++ b/03_monopoly/board.cpp @@ -0,0 +1,209 @@ +#include "board.h" + +#include + +#include "player_loader.h" +#include "tile_loader.h" + +Player *Board::get_current_player() { + return _active_players[_current_player_index]; +} +Player *Board::get_previous_player() { + return _previous_player; +} + +int Board::get_turn() const { + return _turn; +} +void Board::set_turn(const int turn) { + _turn = turn; +} + +Vector Board::get_tiles() const { + return _tiles; +} +void Board::set_tiles(const Vector &tiles) { + _tiles = tiles; +} + +Vector Board::get_active_players() const { + return _active_players; +} +void Board::set_active_players(const Vector &players) { + _active_players = players; +} + +Vector Board::get_lost_players() const { + return _lost_players; +} +void Board::set_lost_players(const Vector &players) { + _lost_players = players; +} + +void Board::load(const String &tile_file, const String &player_file) { + clear(); + + _tiles = TileLoader::load_tile_file(tile_file); + _active_players = PlayerLoader::load_player_file(player_file); +} + +void Board::load_players(const String &file) { + clear_players(); + + _active_players = PlayerLoader::load_player_file(file); +} +void Board::load_tiles(const String &file) { + for (int i = 0; i < _tiles.size(); ++i) { + delete _tiles[i]; + } + + _tiles = TileLoader::load_tile_file(file); +} + +void Board::step() { + Player *cp = _active_players[_current_player_index]; + + printf("Player - %s's turn.\n", cp->get_name().c_str()); + + int jail_time = cp->get_jail_time(); + + if (jail_time > 0) { + --jail_time; + + printf("Player - is in jail for %d more turns.\n", jail_time); + + cp->set_jail_time(jail_time); + + return; + } + + int t = cp->throw_dice(); + + int ti = cp->get_tile_index(); + + ti += t; + + if (ti >= _tiles.size()) { + ti = t % _tiles.size(); + } + + cp->set_tile_index(ti); + + Tile *tile = _tiles[ti]; + + tile->on_player_arrived(cp); + + _previous_player = cp; + + if (cp->get_lost()) { + _active_players.remove_keep_order(_current_player_index); + + _lost_players.push_back(cp); + + if (_current_player_index >= _active_players.size()) { + _current_player_index = 0; + } + + return; + } + + ++_current_player_index; + + if (_current_player_index >= _active_players.size()) { + _current_player_index = 0; + } +} +void Board::run() { + while (_active_players.size() > 1 && _turn < 200) { + step(); + + ++_turn; + } + + on_game_finished(); +} + +void Board::on_game_finished() { + if (_active_players.size() != 1) { + printf("The game has been finished! No winner!\n"); + } else { + printf("The game has been finished! %s the winner!\n", _active_players[0]->get_name().c_str()); + } + + printf("The game took %d turns!\n", _turn); +} + +void Board::clear() { + for (int i = 0; i < _tiles.size(); ++i) { + delete _tiles[i]; + } + + for (int i = 0; i < _active_players.size(); ++i) { + delete _active_players[i]; + } + + for (int i = 0; i < _lost_players.size(); ++i) { + delete _lost_players[i]; + } + + _tiles.clear(); + _active_players.clear(); + _lost_players.clear(); +} + +void Board::clear_players() { + for (int i = 0; i < _active_players.size(); ++i) { + delete _active_players[i]; + } + + for (int i = 0; i < _lost_players.size(); ++i) { + delete _lost_players[i]; + } + + _active_players.clear(); + _lost_players.clear(); +} + +void Board::reset() { + _previous_player = nullptr; + _current_player_index = 0; + _turn = 0; + + for (int i = 0; i < _tiles.size(); ++i) { + _tiles[i]->reset(); + } + + clear_players(); +} + +void Board::print() { + printf("Board:\n"); + + printf("Tiles:\n"); + for (int i = 0; i < _tiles.size(); ++i) { + _tiles[i]->print(); + } + + printf("Active players (%d):\n", _active_players.size()); + for (int i = 0; i < _active_players.size(); ++i) { + _active_players[i]->print(); + } + + printf("Lost players (%d):\n", _lost_players.size()); + for (int i = 0; i < _lost_players.size(); ++i) { + _lost_players[i]->print(); + } +} + +Board::Board() { + reset(); +} +Board::Board(const String &tile_file, const String &player_file) { + reset(); + + load(tile_file, player_file); +} + +Board::~Board() { + clear(); +} diff --git a/03_monopoly/board.h b/03_monopoly/board.h new file mode 100644 index 0000000..cabb9fa --- /dev/null +++ b/03_monopoly/board.h @@ -0,0 +1,55 @@ +#ifndef BOARD_H +#define BOARD_H + +#include "player.h" +#include "string.h" +#include "tile.h" +#include "vector.h" + +class Board { +public: + Player *get_current_player(); + Player *get_previous_player(); + + int get_turn() const; + void set_turn(const int turn); + + Vector get_tiles() const; + void set_tiles(const Vector &tiles); + + Vector get_active_players() const; + void set_active_players(const Vector &players); + + Vector get_lost_players() const; + void set_lost_players(const Vector &players); + + void load(const String &tile_file, const String &player_file); + void load_players(const String &file); + void load_tiles(const String &file); + + void step(); + void run(); + + void on_game_finished(); + + void clear(); + void clear_players(); + void reset(); + + void print(); + + Board(); + Board(const String &tile_file, const String &player_file); + virtual ~Board(); + +private: + Vector _tiles; + Vector _active_players; + Vector _lost_players; + + Player *_previous_player; + int _current_player_index; + int _turn; +}; + +#endif \ No newline at end of file diff --git a/03_monopoly/compile.sh b/03_monopoly/compile.sh index 3cf2ebb..cc94c3a 100755 --- a/03_monopoly/compile.sh +++ b/03_monopoly/compile.sh @@ -18,6 +18,8 @@ g++ -Wall -g -c player.cpp -o obj/player.o g++ -Wall -g -c player_loader.cpp -o obj/player_loader.o g++ -Wall -g -c tile_loader.cpp -o obj/tile_loader.o -g++ -Wall -g -c main.cpp -o obj/main.o -g++ -o bin/program obj/string.o obj/math.o obj/tile.o obj/tile_loader.o obj/player.o obj/player_loader.o obj/main.o +g++ -Wall -g -c board.cpp -o obj/board.o + +g++ -Wall -g -c main.cpp -o obj/main.o +g++ -g -o bin/program obj/string.o obj/math.o obj/tile.o obj/tile_loader.o obj/player.o obj/player_loader.o obj/board.o obj/main.o diff --git a/03_monopoly/main.cpp b/03_monopoly/main.cpp index d26a3ba..2662c08 100755 --- a/03_monopoly/main.cpp +++ b/03_monopoly/main.cpp @@ -10,18 +10,19 @@ #include "tile_loader.h" #include "player_loader.h" +#include "board.h" + +#include "math.h" + int main() { + Math::randomize(); - Vector tiles = TileLoader::load_tile_file("tiles.config"); - Vector players = PlayerLoader::load_player_file("players.config"); + Board b; + b.load("tiles.config", "players.config"); - for (int i = 0; i < tiles.size(); ++i) { - tiles[i]->print(); - } + b.run(); - for (int i = 0; i < players.size(); ++i) { - players[i]->print(); - } + b.print(); return 0; } diff --git a/03_monopoly/player.cpp b/03_monopoly/player.cpp index 05b915f..69814eb 100644 --- a/03_monopoly/player.cpp +++ b/03_monopoly/player.cpp @@ -2,6 +2,8 @@ #include +#include "math.h" + String Player::get_name() { return _name; } @@ -23,7 +25,21 @@ int Player::get_money() const { } void Player::set_money(const int val) { + int c = _money - val; + + if (c >= 0) { + printf("Player - %s has gained %d dollars.\n", _name.c_str(), c); + } else { + printf("Player - %s has gained %d dollars.\n", _name.c_str(), -c); + } + _money = val; + + if (_money <= 0) { + _money = 0; + + set_lost(true); + } } int Player::get_jail_time() const { @@ -31,6 +47,10 @@ int Player::get_jail_time() const { } void Player::set_jail_time(const int val) { + if (_jail_time == 0) { + printf("Player - %s has been jailed for %d turns.\n", _name.c_str(), val); + } + _jail_time = val; } @@ -40,19 +60,26 @@ bool Player::get_lost() const { void Player::set_lost(const bool val) { _lost = val; + + if (val) { + on_lose(); + } } bool Player::want_buy(const String &tile_name, int price) { return false; } -void Player::pay_entry_fee(const int val, Player *to) { -} +int Player::throw_dice() { + int t = Math::rand(1, 7); -void Player::throw_dice() { + printf("Player - %s has thrown the dice, and rolled %d.\n", _name.c_str(), t); + + return t; } void Player::on_lose() { + printf("Player - %s has lost the game. And he's sad.\n", _name.c_str()); } void Player::print() { @@ -77,6 +104,7 @@ bool AgressivePlayer::want_buy(const String &tile_name, int price) { return false; } void AgressivePlayer::on_lose() { + printf("Player - %s has lost the game. And he's angry.\n", _name.c_str()); } String AgressivePlayer::get_class_name() { return "AgressivePlayer"; @@ -101,6 +129,7 @@ bool TrickyPlayer::want_buy(const String &tile_name, int price) { return false; } void TrickyPlayer::on_lose() { + printf("Player - %s has lost the game.\n", _name.c_str()); } String TrickyPlayer::get_class_name() { return "TrickyPlayer"; @@ -113,6 +142,7 @@ bool HumanPlayer::want_buy(const String &tile_name, int price) { return false; } void HumanPlayer::on_lose() { + printf("Player - %s has lost the game. And he's really sad.\n", _name.c_str()); } String HumanPlayer::get_class_name() { return "HumanPlayer"; @@ -124,9 +154,15 @@ HumanPlayer::HumanPlayer() : bool CheatingPlayer::want_buy(const String &tile_name, int price) { return false; } -void CheatingPlayer::throw_dice() { +int CheatingPlayer::throw_dice() { + int t = Math::rand(3, 7); + + printf("Player - %s has thrown the dice, and rolled %d.\n", _name.c_str(), t); + + return t; } void CheatingPlayer::on_lose() { + printf("Player - %s has lost the game. And he's really angry.\n", _name.c_str()); } String CheatingPlayer::get_class_name() { return "CheatingPlayer"; diff --git a/03_monopoly/player.h b/03_monopoly/player.h index 1abd864..3ca1c81 100644 --- a/03_monopoly/player.h +++ b/03_monopoly/player.h @@ -21,8 +21,7 @@ public: void set_lost(const bool val); virtual bool want_buy(const String &tile_name, int price); - virtual void pay_entry_fee(const int val, Player *to); - virtual void throw_dice(); + virtual int throw_dice(); virtual void on_lose(); virtual void print(); @@ -83,7 +82,7 @@ public: class CheatingPlayer : public Player { public: bool want_buy(const String &tile_name, int price); - void throw_dice(); + int throw_dice(); void on_lose(); String get_class_name(); diff --git a/03_monopoly/player_loader.cpp b/03_monopoly/player_loader.cpp index c9ede64..4218122 100644 --- a/03_monopoly/player_loader.cpp +++ b/03_monopoly/player_loader.cpp @@ -39,12 +39,11 @@ Vector PlayerLoader::load_player_file(const String &file_name) { f >> money >> name; - p->set_money(money); - String n(name.c_str()); - p->set_name(n); + p->set_money(money); + players.push_back(p); } } diff --git a/03_monopoly/string.cpp b/03_monopoly/string.cpp index 2c74d8c..e4beb49 100644 --- a/03_monopoly/string.cpp +++ b/03_monopoly/string.cpp @@ -258,6 +258,10 @@ String::String() { _actual_size = 0; _size = 0; _grow_by = 100; + + ensure_capacity(100); + + _data[0] = '\0'; } String::String(const String &other) { @@ -272,6 +276,8 @@ String::String(const String &other) { for (int i = 0; i < other._size; ++i) { _data[i] = other._data[i]; } + + _data[other._size] = '\0'; } String::String(const String &other, int grow_by) { diff --git a/03_monopoly/tile.cpp b/03_monopoly/tile.cpp index 010660a..557bf92 100644 --- a/03_monopoly/tile.cpp +++ b/03_monopoly/tile.cpp @@ -2,6 +2,8 @@ #include +#include "math.h" + String Tile::get_name() { return _name; } @@ -11,6 +13,11 @@ void Tile::set_name(const String &name) { } void Tile::on_player_arrived(Player *p) { + printf("Player %s just stepped on %s.\n", p->get_name().c_str(), _name.c_str()); +} + +void Tile::reset() { + } void Tile::print() { @@ -31,9 +38,16 @@ int TaxTile::get_tax() const { return _tax; } void TaxTile::set_tax(const int tax) { + _tax = tax; } void TaxTile::on_player_arrived(Player *p) { + Tile::on_player_arrived(p); + + p->set_money(p->get_money() - _tax); +} +void TaxTile::print() { + printf("Tile - %s - Name: %s, tax: %d\n", get_class_name().c_str(), get_name().c_str(), _tax); } String TaxTile::get_class_name() { return "TaxTile"; @@ -41,6 +55,8 @@ String TaxTile::get_class_name() { TaxTile::TaxTile() : Tile() { + + _tax = 0; } int OwnableTile::get_price() const { @@ -65,6 +81,49 @@ void OwnableTile::set_owner(Player *val) { } void OwnableTile::on_player_arrived(Player *p) { + Tile::on_player_arrived(p); + + if (!_owner) { + printf("Tile - %s is for sale! It costs %d.\n", get_name().c_str(), _price); + + int m = p->get_money(); + + if (m < _price) { + printf("Player - %s, can't buy tile, not enough money!\n", p->get_name().c_str()); + return; + } + + printf("Player - %s, do you want to buy?\n", p->get_name().c_str()); + + if (p->want_buy(get_name(), _price)) { + printf("Player - %s now owns %s.\n", p->get_name().c_str(), get_name().c_str()); + + _owner = p; + } + } else { + if (p == _owner) { + printf("Tile - %s is now owned by you. Welcome!\n", get_name().c_str()); + return; + } + + printf("Tile - %s is owned by %s. You need to pay an entry fee of %d!\n", get_name().c_str(), p->get_name().c_str(), _enter_price); + + int m = p->get_money(); + + if (m <= _enter_price) { + _owner->set_money(_owner->get_money() + m); + p->set_money(0); + } else { + _owner->set_money(_owner->get_money() + _enter_price); + p->set_money(m - _enter_price); + } + } +} +void OwnableTile::print() { + printf("Tile - %s - Name: %s, price: %d, enter_price: %d, owner: %s.\n", get_class_name().c_str(), get_name().c_str(), _price, _enter_price, _owner ? _owner->get_name().c_str() : "None"); +} +void OwnableTile::reset() { + _owner = nullptr; } String OwnableTile::get_class_name() { return "OwnableTile"; @@ -72,6 +131,10 @@ String OwnableTile::get_class_name() { OwnableTile::OwnableTile() : Tile() { + + _price = 0; + _enter_price = 0; + _owner = nullptr; } int GainTile::get_gain() const { @@ -82,6 +145,12 @@ void GainTile::set_gain(const int val) { } void GainTile::on_player_arrived(Player *p) { + Tile::on_player_arrived(p); + + p->set_money(p->get_money() - _gain); +} +void GainTile::print() { + printf("Tile - %s - Name: %s, gain: %d.\n", get_class_name().c_str(), get_name().c_str(), _gain); } String GainTile::get_class_name() { return "GainTile"; @@ -89,6 +158,8 @@ String GainTile::get_class_name() { GainTile::GainTile() : Tile() { + + _gain = 0; } int LuckTile::get_chance() const { @@ -113,6 +184,18 @@ void LuckTile::set_gain_max(const int val) { } void LuckTile::on_player_arrived(Player *p) { + Tile::on_player_arrived(p); + + int c = Math::rand(0, 100); + + if (c < _chance) { + int v = Math::rand(_gain_min, _gain_max); + + p->set_money(p->get_money() + v); + } +} +void LuckTile::print() { + printf("Tile - %s - Name: %s, chance: %d, gain_min: %d, gain_max: %d.\n", get_class_name().c_str(), get_name().c_str(), _chance, _gain_min, _gain_max); } String LuckTile::get_class_name() { return "LuckTile"; @@ -120,6 +203,10 @@ String LuckTile::get_class_name() { LuckTile::LuckTile() : Tile() { + + _chance = 0; + _gain_min = 0; + _gain_max = 0; } int JailTile::get_jail_time() const { @@ -130,6 +217,12 @@ void JailTile::set_jail_time(const int val) { } void JailTile::on_player_arrived(Player *p) { + Tile::on_player_arrived(p); + + p->set_jail_time(_jail_time); +} +void JailTile::print() { + printf("Tile - %s - Name: %s, jail_time: %d.\n", get_class_name().c_str(), get_name().c_str(), _jail_time); } String JailTile::get_class_name() { return "JailTile"; @@ -137,4 +230,6 @@ String JailTile::get_class_name() { JailTile::JailTile() : Tile() { + + _jail_time = 0; } diff --git a/03_monopoly/tile.h b/03_monopoly/tile.h index 898b26f..c37492e 100644 --- a/03_monopoly/tile.h +++ b/03_monopoly/tile.h @@ -10,6 +10,8 @@ public: virtual void on_player_arrived(Player *p); + virtual void reset(); + virtual void print(); virtual String get_class_name(); @@ -26,6 +28,7 @@ public: void set_tax(const int tax); void on_player_arrived(Player *p); + void print(); String get_class_name(); TaxTile(); @@ -46,6 +49,9 @@ public: void set_owner(Player *val); void on_player_arrived(Player *p); + void print(); + void reset(); + String get_class_name(); OwnableTile(); @@ -62,6 +68,7 @@ public: void set_gain(const int val); void on_player_arrived(Player *p); + void print(); String get_class_name(); GainTile(); @@ -82,6 +89,7 @@ public: void set_gain_max(const int val); void on_player_arrived(Player *p); + void print(); String get_class_name(); LuckTile(); @@ -98,6 +106,7 @@ public: void set_jail_time(const int val); void on_player_arrived(Player *p); + void print(); String get_class_name(); JailTile(); diff --git a/03_monopoly/tile_loader.cpp b/03_monopoly/tile_loader.cpp index ba234f2..a623e80 100644 --- a/03_monopoly/tile_loader.cpp +++ b/03_monopoly/tile_loader.cpp @@ -1,8 +1,8 @@ #include "tile_loader.h" +#include "tile.h" #include #include -#include "tile.h" Vector TileLoader::load_tile_file(const String &file_name) { Vector tiles; @@ -14,31 +14,70 @@ Vector TileLoader::load_tile_file(const String &file_name) { while (!f.eof()) { std::string class_name; + std::string tile_name; - f >> class_name; + f >> class_name >> tile_name; - Tile *t = nullptr; + Tile *t = nullptr; if (class_name == "Tile") { t = new Tile(); } else if (class_name == "TaxTile") { - t = new TaxTile(); + TaxTile *tt = new TaxTile(); + + int tax; + + f >> tax; + + tt->set_tax(tax); + t = tt; } else if (class_name == "OwnableTile") { - t = new OwnableTile(); + OwnableTile *tt = new OwnableTile(); + + int price; + int enter_price; + + f >> price >> enter_price; + + tt->set_price(price); + tt->set_enter_price(enter_price); + + t = tt; } else if (class_name == "GainTile") { - t = new GainTile(); + GainTile *tt = new GainTile(); + + int gain; + + f >> gain; + + tt->set_gain(gain); + t = tt; } else if (class_name == "LuckTile") { - t = new LuckTile(); + LuckTile *tt = new LuckTile(); + + int chance; + int gain_min; + int gain_max; + + f >> chance >> gain_min >> gain_max; + + tt->set_chance(chance); + tt->set_gain_min(gain_min); + tt->set_gain_max(gain_max); + t = tt; } else if (class_name == "JailTile") { - t = new JailTile(); + JailTile *tt = new JailTile(); + + int jail_time; + + f >> jail_time; + + tt->set_jail_time(jail_time); + t = tt; } if (t) { - std::string name; - - f >> name; - - String n(name.c_str()); + String n(tile_name.c_str()); t->set_name(n); diff --git a/03_monopoly/tiles.config b/03_monopoly/tiles.config index fc54d86..e60d608 100644 --- a/03_monopoly/tiles.config +++ b/03_monopoly/tiles.config @@ -1,6 +1,12 @@ Tile Asf -TaxTile aAA -OwnableTile fqfqfdg -GainTile fffqq -LuckTile Qewew -JailTile Fqqfq +TaxTile aAA 3433 +TaxTile dqdq 3433 +OwnableTile fqfqfdg 222 22 +GainTile fffqq 100 +TaxTile aArrrrA 3433 +LuckTile Qewew 50 100 200 +TaxTile dqwd 3433 +JailTile Fqqfq 3 +TaxTile qweq 3433 +TaxTile qweq 3433 +TaxTile qweqw 3433 diff --git a/03_monopoly/vector.h b/03_monopoly/vector.h index d8371dc..5330100 100644 --- a/03_monopoly/vector.h +++ b/03_monopoly/vector.h @@ -8,6 +8,7 @@ public: void push_back(const T &element); void pop_back(); void remove(const int index); + void remove_keep_order(const int index); void erase(const T &element); void clear(); bool empty() const; @@ -62,6 +63,15 @@ void Vector::remove(const int index) { --_size; } +template +void Vector::remove_keep_order(const int index) { + --_size; + + for (int i = index; i < _size; ++i) { + _data[i] = _data[i + 1]; + } +} + template void Vector::erase(const T &element) { int index = find(element);