Skip to content

Instantly share code, notes, and snippets.

@Rapptz
Created March 10, 2014 03:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Rapptz/9459087 to your computer and use it in GitHub Desktop.
Save Rapptz/9459087 to your computer and use it in GitHub Desktop.
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <random>
#include <map>
#include <stdexcept>
#include <functional>
#include <cstdlib>
void print(const char* str) {
while(*str) {
if(*str == '%') {
if(*(str + 1) == '%') {
++str;
}
else {
throw std::runtime_error("invalid format string: missing arguments");
}
}
std::cout << *str++;
}
}
template<typename T, typename... Args>
void print(const char* str, T&& value, Args&& ... args) {
while(*str) {
if(*str == '%') {
if(*(str + 1) == '%') {
++str;
}
else {
std::cout << std::forward<T>(value);
print(str + 1, std::forward<Args>(args)...);
return;
}
}
std::cout << *str++;
}
throw std::logic_error("extra arguments provided to print");
}
struct Card {
private:
int att = 1;
int def = 1;
public:
constexpr Card() = default;
constexpr Card(int attack, int defence = 1): att(attack), def(defence) {}
friend auto operator<<(std::ostream& out, const Card& c) -> decltype(out) {
return out << "ATT: " << c.att << ", DEF: " << c.def << "\n";
}
constexpr bool dead() noexcept {
return def <= 0;
}
void battle(Card& other) {
other.def -= att;
def -= other.att;
}
};
static std::random_device rd;
static std::mt19937 g(rd());
struct Deck {
private:
std::vector<Card> cards;
public:
Deck(): cards(20) {
std::generate(std::begin(cards), std::end(cards), [] {
static std::uniform_int_distribution<> gen(1, 20);
return Card{ gen(g), gen(g) };
});
}
Card draw() {
if(cards.empty()) {
return {};
}
Card copy = cards.back();
cards.pop_back();
return copy;
}
void shuffle() {
std::shuffle(std::begin(cards), std::end(cards), g);
}
bool empty() {
return cards.empty();
}
auto cards_left() -> decltype(cards.size()) {
return cards.size();
}
};
struct Player {
private:
friend class Game;
Deck deck;
Card hand;
public:
std::string name = "anonymous";
Player() = default;
Player(std::string name): name(std::move(name)) {}
void battle(Player& other) {
print("% is attacking %!\n", name, other.name);
hand.battle(other.hand);
if(other.hand.dead()) {
other.draw();
}
if(hand.dead()) {
draw();
}
}
void draw() {
hand = deck.draw();
}
bool lost() {
return deck.empty();
}
};
struct Game {
private:
Player one;
Player two;
Player* current;
Player* other;
std::map<std::string, std::function<bool()>> commands;
bool running = true;
public:
Game() {
one.deck.shuffle();
two.deck.shuffle();
one.draw();
two.draw();
current = &one;
other = &two;
commands["help"] = [this] {
print("available commands: \n");
for(auto && c : commands) {
print("%\n", c.first);
}
return true;
};
commands["attack"] = [this] {
current->battle(*other);
return false;
};
commands["status"] = [this] {
print("Cards left in your deck: %\n", current->deck.cards_left());
return true;
};
commands["clear"] = [] {
std::system("cls"); // evil!
return true;
};
}
void check_loss() {
if(other->lost()) {
print("% losses!\n% wins!\n", other->name, current->name);
running = false;
}
else if(current->lost()) {
print("% losses!\n% wins!\n", current->name, other->name);
running = false;
}
}
void process_input() {
print("What would you like to do? (type help for commands): ");
std::string command;
while(std::getline(std::cin, command)) {
auto it = commands.find(command);
if(it == commands.end()) {
commands.at("help")();
}
else if(!it->second()) {
break;
}
print("What would you like to do? (type help for commands): ");
}
}
void turn() {
print("It is currently %'s turn\n", current->name);
process_input();
check_loss();
using std::swap;
swap(current, other);
}
int run() {
print("What is your name player one? ");
std::string name;
std::getline(std::cin, name);
one.name = std::move(name);
print("Welcome to the game %!\n", one.name);
two.name = "Bob";
while(running) {
print("%: %", one.name, one.hand);
print("%: %", two.name, two.hand);
turn();
}
return 0;
}
};
int main() {
Game game;
return game.run();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment