Commit 2f013926 authored by aggsol's avatar aggsol

initial commit

parents
books/*.xml
CMakeLists.txt.user
CMakeCache.txt
CMakeFiles
CMakeScripts
Testing
Makefile
cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.ldcmake
build
*~
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
# cache files for sublime text
*.tmlanguage.cache
*.tmPreferences.cache
*.stTheme.cache
# workspace files are user-specific
*.sublime-workspace
# project files should be checked into the repository, unless a significant
# proportion of contributors will probably not be using SublimeText
# *.sublime-project
# sftp configuration file
sftp-config.json
# Package control specific files
Package Control.last-run
Package Control.ca-list
Package Control.ca-bundle
Package Control.system-ca-bundle
Package Control.cache/
Package Control.ca-certs/
Package Control.merged-ca-bundle
Package Control.user-ca-bundle
oscrypto-ca-bundle.crt
bh_unicode_properties.cache
# Sublime-github package stores a github token in this file
# https://packagecontrol.io/packages/sublime-github
GitHub.sublime-settings
cmake_minimum_required(VERSION 3.8)
project("gamebook-combat" VERSION 0.1.0 LANGUAGES CXX)
# Create compile_commands.json for cppcheck
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Default build type: Debug
# Set it on the command line: -DCMAKE_BUILD_TYPE=Release)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build (Debug or Release)" FORCE)
endif()
IF(CMAKE_BUILD_TYPE MATCHES Debug)
message(STATUS "Debug build.")
add_definitions(-DDEBUG)
add_compile_options(-O3 -g)
ELSEIF(CMAKE_BUILD_TYPE MATCHES Release)
message(STATUS "Release build.")
add_definitions(-DNDEBUG)
add_compile_options(-O2 -s)
ELSE()
message(WARNING "Unknown build type.")
ENDIF()
# Copy binaries to root build dir
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
add_subdirectory(src)
message(STATUS "Version = ${PROJECT_VERSION}")
\ No newline at end of file
cmake_minimum_required(VERSION 3.8)
# Fighting Fantasy combat
add_executable("ff-combat" ff-combat.cpp)
target_compile_features("ff-combat" PRIVATE cxx_std_14)
target_compile_definitions("ff-combat" PRIVATE _FORTIFY_SOURCE=2)
target_compile_options("ff-combat" PRIVATE
-Wall -Wextra -Wshadow -Wnon-virtual-dtor -Wold-style-cast -Woverloaded-virtual -Wzero-as-null-pointer-constant
-pedantic -fPIE -fstack-protector-all -fno-rtti
)
# Lone Wolf combat
add_executable("lw-combat"
lw-combat.cpp
CombatResultTable.cpp
)
target_compile_features("lw-combat" PRIVATE cxx_std_14)
target_compile_definitions("lw-combat" PRIVATE _FORTIFY_SOURCE=2)
target_compile_options("lw-combat" PRIVATE
-Wall -Wextra -Wshadow -Wnon-virtual-dtor -Wold-style-cast -Woverloaded-virtual -Wzero-as-null-pointer-constant
-pedantic -fPIE -fstack-protector-all -fno-rtti
)
/**
* Command Line Arguments
* Adhering the POSIX and GNU command line parameter standards.
*
* POSIX:
* Arguments are options if they begin with a hyphen delimiter (‘-’).
* Options are a hyphen followed by a single alphanumeric character: '-o'
* Options may require an argument: '-o argument' or '-oargument'
* Options without arguments are of type bool and true when set
* Options without arguments can be grouped after a hyphen: '-lst' same as '-t -l -s'
* Options can appear in any order: '-lst' same as '-tls'
* The '--' argument terminates options, following arguments are non-options
*
* GNU:
* Define long name options: '--output' for '-o'
* Always provide '-h', '--help' and '--version' options.
*
* Usage:
*
* bodhi::CliArguments args(argc, argv);
*
* auto name = args.getOpt<std::string>("n", "name", "none");
* auto count = args.getOpt<int>("c", "count", -1);
*
* auto version = args.getOpt("", "version");
* auto help = args.getOpt("h", "help");
*
* Version: 2.0.1
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <foss@aggsol.de> wrote this file. As long as you retain this
* notice you can do whatever you want with this stuff. If we meet some day,
* and you think this stuff is worth it, you can buy me a beer in return KIM
* ----------------------------------------------------------------------------
*/
#ifndef BODHI_CLI_ARGUMENTS_HPP
#define BODHI_CLI_ARGUMENTS_HPP
#include <cassert>
#include <deque>
#include <iostream>
#include <string>
#include <sstream>
#include <stdexcept>
namespace bodhi
{
class CliArguments
{
public:
CliArguments(int argc, const char* const argv[])
: m_arguments()
, m_value()
{
if(argc < 1)
{
throw std::invalid_argument("Invalid argc.");
}
if(argv == nullptr)
{
throw std::invalid_argument("Invalid argv.");
}
// NOTE: skip the first, that is the program name
for(int i=1; i<argc; ++i)
{
m_arguments.push_back(argv[i]);
}
}
/*
* Returns the remaining arguments
*/
const std::deque<std::string>& arguments() const { return m_arguments; }
/*
* Returns the value of long or short options if found, fallback value otherwise
*/
template <typename T>
T getOpt(const std::string& opt, const std::string& longOpt, const T& fallback )
{
static_assert(! std::is_same<T, bool>::value, "Use bool specialisation");
if(opt.length() > 1)
{
throw std::invalid_argument("Short option must be one character or empty.");
}
if(longOpt.length() == 1)
{
throw std::invalid_argument("Long option must not be one character.");
}
if(m_arguments.size() == 0) return fallback;
if(! search(opt))
{
if(! search(longOpt))
{
if(! searchCondensed(opt))
{
return fallback;
}
}
}
T value;
std::istringstream(m_value) >> value;
return value;
}
bool getOpt(const std::string& opt, const std::string& longOpt)
{
if(opt.length() > 1)
{
throw std::invalid_argument("Short option must be one character or empty.");
}
if(longOpt.length() == 1)
{
throw std::invalid_argument("Long option must not be one character.");
}
for(unsigned i=0; i<m_arguments.size(); ++i)
{
std::string& arg = m_arguments.at(i);
if(arg.size() < 2) continue;
// condensed bool options -xyz
if(opt.length() == 1 && arg[0] == '-' && arg[1] != '-')
{
auto pos = arg.find(opt);
if(pos != std::string::npos)
{
arg.erase(pos, 1);
if(arg == "-") // removed all bool options
{
m_arguments.erase(m_arguments.begin() + i);
}
return true;
}
}
else if(arg[0] == '-' && arg[1] == '-')
{
// skip '--'
if(arg.length() == 2) return false;
if(arg.substr(2) == longOpt)
{
m_arguments.erase( m_arguments.begin() + i);
return true;
}
}
}
return false;
}
private:
/**
* Search for condensed options like -x123
* Returns true if found, false otherwise
*/
bool searchCondensed(const std::string& name)
{
if(name.empty()) return false;
assert(name.size() == 1);
for(unsigned i=0; i<(m_arguments.size()); ++i)
{
const std::string& arg = m_arguments.at(i);
if(arg.size() < 3) continue;
if(arg[0] == '-' && arg[1] != '-')
{
if(arg.substr(1, 1) == name)
{
m_value = arg.substr(2);
m_arguments.erase(m_arguments.begin() + i);
return true;
}
}
}
return false;
}
/**
* Search for the named options and erase it and its value.
* The value is copied to m_value.
* Returns true when found, false otherwise.
*/
bool search(const std::string& name)
{
if(name.empty()) return false;
for(unsigned i=0; i<(m_arguments.size() - 1); ++i)
{
const std::string& arg = m_arguments.at(i);
if(arg.size() < 2) continue;
if(arg[0] == '-' && arg[1] != '-')
{
if(arg.substr(1) == name)
{
m_value = m_arguments.at(i + 1);
// erase option and its value
m_arguments.erase( m_arguments.begin() + i, m_arguments.begin() + i + 2);
return true;
}
}
else if(arg[0] == '-' && arg[1] == '-')
{
// skip '--'
if(arg.length() == 2) return false;
if(arg.substr(2) == name)
{
m_value = m_arguments.at(i + 1);
// erase option and its value
m_arguments.erase( m_arguments.begin() + i, m_arguments.begin() + i + 2);
return true;
}
}
}
return false;
}
std::deque<std::string> m_arguments;
std::string m_value;
};
}
#endif
#ifndef BODHI_COMBAT_RESULT_TABLE_HPP
#define BODHI_COMBAT_RESULT_TABLE_HPP
namespace bodhi
{
struct CombatResult
{
int LoneWolf;
int Enemy;
}
class CombatResultTable
{
public:
const CombatResult& getCombatResult(int combatRatio, int randomNum);
private:
};
}
#endif
\ No newline at end of file
#include "CliArguments.hpp"
#include "rang.hpp"
#include <chrono>
#include <iomanip>
#include <functional>
#include <random>
int main(int argc, char* argv[])
{
bodhi::CliArguments args(argc, argv);
auto version = args.getOpt("", "version");
auto help = args.getOpt("h", "help");
auto noLuck = args.getOpt("n", "no-luck");
// if(args.arguments().size() != 4 || help)
// {
// std::cerr << "ff-combat <hero skill> <hero stamina> <enemy skill> <enemy stamina>\n";
// return 101;
// }
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
std::mt19937 generator(seed);
std::uniform_int_distribution<int> distribution(1, 6);
auto dice = std::bind (distribution, generator);
int heroSkill = 6 + dice();
int heroStamina = dice() + dice() + dice() + dice();
int heroLuck = 6 + dice();
int enemySkill = 3 + dice();
int enemyStamina = 6 + dice();
std::cout << "YOU : Skill=" << std::setw(2) << heroSkill
<< " Stamina=" << std::setw(2) << heroStamina << " Luck=" << std::setw(2) << heroLuck << "\n";
std::cout << "Enemy: Skill=" << std::setw(2) << enemySkill
<< " Stamina=" << std::setw(2) << enemyStamina << "\n";
bool end = false;
int rounds = 1;
while(not end)
{
int heroAttack = heroSkill + dice() + dice();
int enemyAttack = enemySkill + dice() + dice();
std::cout << "Round " << std::setw(2) << rounds
<< ": YOUR attack=" << std::setw(2) << heroAttack
<< " Enemy attack=" << std::setw(2) << enemyAttack << "\n";
if(heroAttack > enemyAttack)
{
enemyStamina -= 2;
std::cout << rang::fg::green << "Enemy is hit! Stamina=" << std::setw(2) << enemyStamina << "\n" << rang::fg::reset;
}
else if(enemyAttack > heroAttack)
{
heroStamina -= 2;
std::cout << rang::fg::red << "YOU are hit! Stamina=" << std::setw(2) << heroStamina << "\n" << rang::fg::reset;
}
else
{
std::cout << rang::fg::yellow << "Weapons clang together.\n" << rang::fg::reset;
}
if(heroStamina < 0)
{
std::cout << rang::fg::red << "YOU died. YOUR adventure ends here.\n" << rang::fg::reset;
end = true;
}
if(enemyStamina < 0)
{
std::cout << "YOU defeated the enemy.\n";
end = true;
}
rounds++;
}
return 0;
}
\ No newline at end of file
#include "CliArguments.hpp"
#include "rang.hpp"
#include <chrono>
#include <iomanip>
#include <functional>
#include <random>
int main(int argc, char* argv[])
{
bodhi::CliArguments args(argc, argv);
auto version = args.getOpt("", "version");
auto help = args.getOpt("h", "help");
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
std::mt19937 generator(seed);
std::uniform_int_distribution<int> distribution(0, 9);
auto dice = std::bind (distribution, generator);
return 0;
}
\ No newline at end of file
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment