From 885a937fcf336b9f984f102c9799e43762687b67 Mon Sep 17 00:00:00 2001 From: happyme531 <2302004040@qq.com> Date: Wed, 29 Apr 2020 23:28:28 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E4=BA=94=E4=B8=AA?= =?UTF-8?q?=E9=9A=8F=E6=9C=BA=E4=BA=8B=E4=BB=B6(=E4=B8=8D=E8=83=BD?= =?UTF-8?q?=E9=80=9A=E8=BF=87=E9=9A=8F=E6=9C=BA=E4=BA=8B=E4=BB=B6=E5=A2=99?= =?UTF-8?q?=E8=A7=A6=E5=8F=91)=EF=BC=8C=E5=8A=A0=E5=85=A5=E5=91=BD?= =?UTF-8?q?=E4=BB=A4=E8=A1=8C=E9=80=89=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 56 +- CMakeLists.txt | 6 +- randomEventWall/components/include/cmdline.h | 814 +++++++++++++++++++ randomEventWall/include/logger.h | 8 +- randomEventWall/include/main.h | 3 + randomEventWall/include/randomEventWall.h | 77 ++ randomEventWall/main.cpp | 76 +- randomEventWall/randomEventWall.cpp | 93 +++ randomEventWall/randomPlantWall.cpp | 6 +- 9 files changed, 1117 insertions(+), 22 deletions(-) create mode 100644 randomEventWall/components/include/cmdline.h create mode 100644 randomEventWall/include/randomEventWall.h create mode 100644 randomEventWall/randomEventWall.cpp diff --git a/.vscode/settings.json b/.vscode/settings.json index 3fa460a..48ff785 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,6 +5,60 @@ "*.in": "cpp", "iostream": "cpp", "ostream": "cpp", - "*.rh": "cpp" + "*.rh": "cpp", + "algorithm": "cpp", + "array": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "concepts": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "exception": "cpp", + "fstream": "cpp", + "functional": "cpp", + "initializer_list": "cpp", + "ios": "cpp", + "iosfwd": "cpp", + "istream": "cpp", + "iterator": "cpp", + "limits": "cpp", + "list": "cpp", + "map": "cpp", + "memory": "cpp", + "new": "cpp", + "optional": "cpp", + "queue": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "string": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "typeinfo": "cpp", + "unordered_map": "cpp", + "utility": "cpp", + "vector": "cpp", + "xfacet": "cpp", + "xhash": "cpp", + "xiosbase": "cpp", + "xlocale": "cpp", + "xlocinfo": "cpp", + "xlocnum": "cpp", + "xmemory": "cpp", + "xstddef": "cpp", + "xstring": "cpp", + "xtr1common": "cpp", + "xtree": "cpp", + "xutility": "cpp", + "random": "cpp", + "chrono": "cpp" } } \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index e31def5..6cbe3c2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ project(pvz-randomEventWall) set (pvz-randomEventWall_VERSION_MAJOR 0) set (pvz-randomEventWall_VERSION_MINOR 1) - +set(CMAKE_CXX_FLAGS "/std:c++latest ${CMAKE_CXX_FLAGS}") configure_file( "${PROJECT_SOURCE_DIR}/randomEventWall/include/config.h.in" "${pvz-randomEventWall_BINARY_DIR}/randomEventWall/config.h" @@ -11,7 +11,10 @@ configure_file( aux_source_directory(./randomEventWall DIR_SRCS) aux_source_directory(./randomEventWall/include DIR_SRCS) +aux_source_directory(./randomEventWall/components DIR_SRCS) +aux_source_directory(./randomEventWall/components/include DIR_SRCS) include_directories(DIR_SRCS) + aux_source_directory(./pvzclass/pvzclass DIR_LIB_SRCS) aux_source_directory(./pvzclass/pvzclass/Classes DIR_LIB_SRCS) aux_source_directory(./pvzclass/pvzclass/Enums DIR_LIB_SRCS) @@ -21,7 +24,6 @@ include_directories(DIR_LIB_SRCS) #list(REMOVE_ITEM DIR_LIB_SRCS "pvzclass\pvzclass\pvzclass.cpp" "pvzclass\pvzclass\pvzclass.h") add_library (libpvzclass STATIC ${DIR_LIB_SRCS}) - set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) add_executable(pvz-randomEventWall ${DIR_SRCS}) diff --git a/randomEventWall/components/include/cmdline.h b/randomEventWall/components/include/cmdline.h new file mode 100644 index 0000000..c0a0552 --- /dev/null +++ b/randomEventWall/components/include/cmdline.h @@ -0,0 +1,814 @@ +/* + Copyright (c) 2009, Hideyuki Tanaka + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + THIS SOFTWARE IS PROVIDED BY ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace cmdline{ + +namespace detail{ + +template +class lexical_cast_t{ +public: + static Target cast(const Source &arg){ + Target ret; + std::stringstream ss; + if (!(ss<>ret && ss.eof())) + throw std::bad_cast(); + + return ret; + } +}; + +template +class lexical_cast_t{ +public: + static Target cast(const Source &arg){ + return arg; + } +}; + +template +class lexical_cast_t{ +public: + static std::string cast(const Source &arg){ + std::ostringstream ss; + ss< +class lexical_cast_t{ +public: + static Target cast(const std::string &arg){ + Target ret; + std::istringstream ss(arg); + if (!(ss>>ret && ss.eof())) + throw std::bad_cast(); + return ret; + } +}; + +template +struct is_same { + static const bool value = false; +}; + +template +struct is_same{ + static const bool value = true; +}; + +template +Target lexical_cast(const Source &arg) +{ + return lexical_cast_t::value>::cast(arg); +} + +static inline std::string demangle(const std::string &name) +{ + #ifdef _MSC_VER + return name; // 为MSVC编译器时直接返回name +#elif defined(__GNUC__) + // 为gcc编译器时还调用原来的代码 + int status=0; + char *p=abi::__cxa_demangle(name.c_str(), 0, 0, &status); + std::string ret(p); + free(p); + return ret; +#else +// 其他不支持的编译器需要自己实现这个方法 +#error unexpected c complier (msc/gcc), Need to implement this method for demangle +#endif +} + +template +std::string readable_typename() +{ + return demangle(typeid(T).name()); +} + +template +std::string default_value(T def) +{ + return detail::lexical_cast(def); +} + +template <> +inline std::string readable_typename() +{ + return "string"; +} + +} // detail + +//----- + +class cmdline_error : public std::exception { +public: + cmdline_error(const std::string &msg): msg(msg){} + ~cmdline_error() throw() {} + const char *what() const throw() { return msg.c_str(); } +private: + std::string msg; +}; + +template +struct default_reader{ + T operator()(const std::string &str){ + return detail::lexical_cast(str); + } +}; + +template +struct range_reader{ + range_reader(const T &low, const T &high): low(low), high(high) {} + T operator()(const std::string &s) const { + T ret=default_reader()(s); + if (!(ret>=low && ret<=high)) throw cmdline::cmdline_error("range_error"); + return ret; + } +private: + T low, high; +}; + +template +range_reader range(const T &low, const T &high) +{ + return range_reader(low, high); +} + +template +struct oneof_reader{ + T operator()(const std::string &s){ + T ret=default_reader()(s); + if (std::find(alt.begin(), alt.end(), ret)==alt.end()) + throw cmdline_error(""); + return ret; + } + void add(const T &v){ alt.push_back(v); } +private: + std::vector alt; +}; + +template +oneof_reader oneof(T a1) +{ + oneof_reader ret; + ret.add(a1); + return ret; +} + +template +oneof_reader oneof(T a1, T a2) +{ + oneof_reader ret; + ret.add(a1); + ret.add(a2); + return ret; +} + +template +oneof_reader oneof(T a1, T a2, T a3) +{ + oneof_reader ret; + ret.add(a1); + ret.add(a2); + ret.add(a3); + return ret; +} + +template +oneof_reader oneof(T a1, T a2, T a3, T a4) +{ + oneof_reader ret; + ret.add(a1); + ret.add(a2); + ret.add(a3); + ret.add(a4); + return ret; +} + +template +oneof_reader oneof(T a1, T a2, T a3, T a4, T a5) +{ + oneof_reader ret; + ret.add(a1); + ret.add(a2); + ret.add(a3); + ret.add(a4); + ret.add(a5); + return ret; +} + +template +oneof_reader oneof(T a1, T a2, T a3, T a4, T a5, T a6) +{ + oneof_reader ret; + ret.add(a1); + ret.add(a2); + ret.add(a3); + ret.add(a4); + ret.add(a5); + ret.add(a6); + return ret; +} + +template +oneof_reader oneof(T a1, T a2, T a3, T a4, T a5, T a6, T a7) +{ + oneof_reader ret; + ret.add(a1); + ret.add(a2); + ret.add(a3); + ret.add(a4); + ret.add(a5); + ret.add(a6); + ret.add(a7); + return ret; +} + +template +oneof_reader oneof(T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8) +{ + oneof_reader ret; + ret.add(a1); + ret.add(a2); + ret.add(a3); + ret.add(a4); + ret.add(a5); + ret.add(a6); + ret.add(a7); + ret.add(a8); + return ret; +} + +template +oneof_reader oneof(T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8, T a9) +{ + oneof_reader ret; + ret.add(a1); + ret.add(a2); + ret.add(a3); + ret.add(a4); + ret.add(a5); + ret.add(a6); + ret.add(a7); + ret.add(a8); + ret.add(a9); + return ret; +} + +template +oneof_reader oneof(T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8, T a9, T a10) +{ + oneof_reader ret; + ret.add(a1); + ret.add(a2); + ret.add(a3); + ret.add(a4); + ret.add(a5); + ret.add(a6); + ret.add(a7); + ret.add(a8); + ret.add(a9); + ret.add(a10); + return ret; +} + +//----- + +class parser{ +public: + parser(){ + } + ~parser(){ + for (std::map::iterator p=options.begin(); + p!=options.end(); p++) + delete p->second; + } + + void add(const std::string &name, + char short_name=0, + const std::string &desc=""){ + if (options.count(name)) throw cmdline_error("multiple definition: "+name); + options[name]=new option_without_value(name, short_name, desc); + ordered.push_back(options[name]); + } + + template + void add(const std::string &name, + char short_name=0, + const std::string &desc="", + bool need=true, + const T def=T()){ + add(name, short_name, desc, need, def, default_reader()); + } + + template + void add(const std::string &name, + char short_name=0, + const std::string &desc="", + bool need=true, + const T def=T(), + F reader=F()){ + if (options.count(name)) throw cmdline_error("multiple definition: "+name); + options[name]=new option_with_value_with_reader(name, short_name, need, def, desc, reader); + ordered.push_back(options[name]); + } + + void footer(const std::string &f){ + ftr=f; + } + + void set_program_name(const std::string &name){ + prog_name=name; + } + + bool exist(const std::string &name) const { + if (options.count(name)==0) throw cmdline_error("there is no flag: --"+name); + return options.find(name)->second->has_set(); + } + + template + const T &get(const std::string &name) const { + if (options.count(name)==0) throw cmdline_error("there is no flag: --"+name); + const option_with_value *p=dynamic_cast*>(options.find(name)->second); + if (p==NULL) throw cmdline_error("type mismatch flag '"+name+"'"); + return p->get(); + } + + const std::vector &rest() const { + return others; + } + + bool parse(const std::string &arg){ + std::vector args; + + std::string buf; + bool in_quote=false; + for (std::string::size_type i=0; i=arg.length()){ + errors.push_back("unexpected occurrence of '\\' at end of string"); + return false; + } + } + + buf+=arg[i]; + } + + if (in_quote){ + errors.push_back("quote is not closed"); + return false; + } + + if (buf.length()>0) + args.push_back(buf); + + for (size_t i=0; i &args){ + int argc=static_cast(args.size()); + std::vector argv(argc); + + for (int i=0; i lookup; + for (std::map::iterator p=options.begin(); + p!=options.end(); p++){ + if (p->first.length()==0) continue; + char initial=p->second->short_name(); + if (initial){ + if (lookup.count(initial)>0){ + lookup[initial]=""; + errors.push_back(std::string("short option '")+initial+"' is ambiguous"); + return false; + } + else lookup[initial]=p->first; + } + } + + for (int i=1; i &args){ + if (!options.count("help")) + add("help", '?', "print this message"); + check(args.size(), parse(args)); + } + + void parse_check(int argc, char *argv[]){ + if (!options.count("help")) + add("help", '?', "print this message"); + check(argc, parse(argc, argv)); + } + + std::string error() const{ + return errors.size()>0?errors[0]:""; + } + + std::string error_full() const{ + std::ostringstream oss; + for (size_t i=0; imust()) + oss<short_description()<<" "; + } + + oss<<"[options] ... "< ((ordered[i]->name().length()))) ? (max_width) : ((ordered[i]->name().length()))); + } + for (size_t i=0; ishort_name()){ + oss<<" -"<short_name()<<", "; + } + else{ + oss<<" "; + } + + oss<<"--"<name(); + for (size_t j=ordered[i]->name().length(); jdescription()<set()){ + errors.push_back("option needs value: --"+name); + return; + } + } + + void set_option(const std::string &name, const std::string &value){ + if (options.count(name)==0){ + errors.push_back("undefined option: --"+name); + return; + } + if (!options[name]->set(value)){ + errors.push_back("option value is invalid: --"+name+"="+value); + return; + } + } + + class option_base{ + public: + virtual ~option_base(){} + + virtual bool has_value() const=0; + virtual bool set()=0; + virtual bool set(const std::string &value)=0; + virtual bool has_set() const=0; + virtual bool valid() const=0; + virtual bool must() const=0; + + virtual const std::string &name() const=0; + virtual char short_name() const=0; + virtual const std::string &description() const=0; + virtual std::string short_description() const=0; + }; + + class option_without_value : public option_base { + public: + option_without_value(const std::string &name, + char short_name, + const std::string &desc) + :nam(name), snam(short_name), desc(desc), has(false){ + } + ~option_without_value(){} + + bool has_value() const { return false; } + + bool set(){ + has=true; + return true; + } + + bool set(const std::string &){ + return false; + } + + bool has_set() const { + return has; + } + + bool valid() const{ + return true; + } + + bool must() const{ + return false; + } + + const std::string &name() const{ + return nam; + } + + char short_name() const{ + return snam; + } + + const std::string &description() const { + return desc; + } + + std::string short_description() const{ + return "--"+nam; + } + + private: + std::string nam; + char snam; + std::string desc; + bool has; + }; + + template + class option_with_value : public option_base { + public: + option_with_value(const std::string &name, + char short_name, + bool need, + const T &def, + const std::string &desc) + : nam(name), snam(short_name), need(need), has(false) + , def(def), actual(def) { + this->desc=full_description(desc); + } + ~option_with_value(){} + + const T &get() const { + return actual; + } + + bool has_value() const { return true; } + + bool set(){ + return false; + } + + bool set(const std::string &value){ + try{ + actual=read(value); + has=true; + } + catch(const std::exception &e){ + return false; + } + return true; + } + + bool has_set() const{ + return has; + } + + bool valid() const{ + if (need && !has) return false; + return true; + } + + bool must() const{ + return need; + } + + const std::string &name() const{ + return nam; + } + + char short_name() const{ + return snam; + } + + const std::string &description() const { + return desc; + } + + std::string short_description() const{ + return "--"+nam+"="+detail::readable_typename(); + } + + protected: + std::string full_description(const std::string &desc){ + return + desc+" ("+detail::readable_typename()+ + (need?"":" [="+detail::default_value(def)+"]") + +")"; + } + + virtual T read(const std::string &s)=0; + + std::string nam; + char snam; + bool need; + std::string desc; + + bool has; + T def; + T actual; + }; + + template + class option_with_value_with_reader : public option_with_value { + public: + option_with_value_with_reader(const std::string &name, + char short_name, + bool need, + const T def, + const std::string &desc, + F reader) + : option_with_value(name, short_name, need, def, desc), reader(reader){ + } + + private: + T read(const std::string &s){ + return reader(s); + } + + F reader; + }; + + std::map options; + std::vector ordered; + std::string ftr; + + std::string prog_name; + std::vector others; + + std::vector errors; +}; + +} // cmdline \ No newline at end of file diff --git a/randomEventWall/include/logger.h b/randomEventWall/include/logger.h index 9e2afbb..2502d52 100644 --- a/randomEventWall/include/logger.h +++ b/randomEventWall/include/logger.h @@ -2,11 +2,11 @@ #include #include -#define LOG_VERBOSE 1 -#define LOG_DEBUG 2 +#define LOG_VERBOSE 5 +#define LOG_DEBUG 4 #define LOG_INFO 3 -#define LOG_WARN 4 -#define LOG_ERROR 5 +#define LOG_WARN 2 +#define LOG_ERROR 1 extern int logLevel; diff --git a/randomEventWall/include/main.h b/randomEventWall/include/main.h index 179a6e2..1130cea 100644 --- a/randomEventWall/include/main.h +++ b/randomEventWall/include/main.h @@ -10,9 +10,12 @@ #include #include #include +#include +#include using namespace std; extern PVZ* pvz; +extern mt19937 mt19937rng; #endif \ No newline at end of file diff --git a/randomEventWall/include/randomEventWall.h b/randomEventWall/include/randomEventWall.h new file mode 100644 index 0000000..fe9ff1f --- /dev/null +++ b/randomEventWall/include/randomEventWall.h @@ -0,0 +1,77 @@ +#pragma once +#include +#include "main.h" +typedef struct randomEvent { + //该事件的幸运程度 + int luck; + //事件名 + string name; + //触发该事件对应的函数 + bool (*trigger)(void); + +} randomEvent_t; + +class randomEventWall { + public: + randomEventWall(/* args */); + ~randomEventWall(); + void trigger(Plant* brokenPlant); + + private: + static bool addSun_(); + static bool removeSun_(); + static bool reverseSun_(); + static bool addSomeNormalZombiesAtStartLine_(); + static bool addSomeNormalZombiesInLawn_(); + static bool removeSomeZombiesInLawn_(); + static bool addABalloonZombie_(); + + public: + //下面是所有的随机事件 + const randomEvent_t addSun = { + .luck = 30, .name = "添加随机阳光", .trigger = &addSun_}; + const randomEvent_t removeSun = { + .luck = -30, .name = "扣除随机阳光", .trigger = &removeSun_}; + const randomEvent_t reverseSun = { + .luck = -20, .name = "反转阳光数值", .trigger = &reverseSun_}; + const randomEvent_t addSomeNormalZombiesAtStartLine = { + .luck = -12, + .name = "在起点生成一些普通僵尸", + .trigger = &addSomeNormalZombiesAtStartLine_}; + const randomEvent_t addSomeNormalZombiesInLawn{ + .luck = -17, + .name = "在场景中靠右生成一些普通僵尸", + .trigger = &addSomeNormalZombiesInLawn_}; + const randomEvent_t removeSomeZombiesInLawn{ + .luck = 20, + .name = "移除场景内一些僵尸", + .trigger = &removeSomeZombiesInLawn_}; + const randomEvent_t addABalloonZombie{ + .luck = -70, + .name = "生成一个气球僵尸", + .trigger = &addABalloonZombie_}; + randomEvent_t generateRandomPlants; + randomEvent_t generateRandomPlantsInRow; + randomEvent_t generateRandomPlantsInColumn; + randomEvent_t removePlants; + randomEvent_t removePlantsInRow; + randomEvent_t removePlantsInColumn; + randomEvent_t launchAllLawnMovers; + randomEvent_t resetAllLawnMovers; + + randomEvent_t (randomEvents[15]) = {addSun, + removeSun, + reverseSun, + addSomeNormalZombiesAtStartLine, + addSomeNormalZombiesInLawn, + removeSomeZombiesInLawn, + addABalloonZombie, + generateRandomPlants, + generateRandomPlantsInRow, + generateRandomPlantsInColumn, + removePlants, + removePlantsInRow, + removePlantsInColumn, + launchAllLawnMovers, + resetAllLawnMovers}; +}; diff --git a/randomEventWall/main.cpp b/randomEventWall/main.cpp index befd773..2dace9b 100644 --- a/randomEventWall/main.cpp +++ b/randomEventWall/main.cpp @@ -1,22 +1,33 @@ #include "include/main.h" #include "include/randomPlantWall.h" +#include "include/randomEventWall.h" #include "include/logger.h" +#include "components/include/cmdline.h" + #include "../pvzclass/pvzclass/utils.h" #define RANDOMEVENTWALL_VERSION 0.1 -int logLevel = 5; + using namespace std; +int logLevel = 5; + PVZ* pvz = nullptr; +mt19937 mt19937rng(0); randomPlantWall rpw; +randomEventWall rew; + +template +int length(T& arr) +{ + return sizeof(arr) / sizeof(arr[0]); +} void onPlantRemove(Event* e) { Plant* plant = ((EventPlantRemove*)e)->plant; rpw.trigger(plant); }; -void onPlantPlant(Event* e){ -} //经典的随机事件墙关卡:向日葵,荷叶,随机墙,随机事件墙 //(向日葵,荷叶,坚果墙,阳光菇) @@ -34,15 +45,41 @@ void initClassicRandomWall() { Utils::SetPlantCost(PlantType::Wallnut, 150); }; -int main() { - //启动时的输出 - cout << yellow << "===植物大战僵尸 随机事件墙===" << endl; - cout << yellow << "===by 快乐的我531/hallo1===" << endl; +int testEvent=0; +int main(int argc, char* argv[], char* env[]) { + //解析参数 + cmdline::parser par; + par.add("version",'v',"显示程序版本"); + par.add("hide-banner",'\0',"禁用程序启动时输出的信息"); + par.add("list-events",'\0',"列出所有可用的事件(名称与id)"); + par.add("test-event",'\0',"<事件id> 执行一个事件之后退出",false,0,cmdline::range(1,length(rew.randomEvents))); + par.add("log-level",'\0',"<等级> 改变日志等级(0~5)",false,5); + par.parse_check(argc,argv); + testEvent=par.get("test-event"); + logLevel=par.get("log-level"); - cout << green << "随机事件墙版本:" << RANDOMEVENTWALL_VERSION << endl; - cout << green << "pvzclass版本:" << pvz->Version << endl; - cout << green << "编译时间: " << __DATE__ << " " << __TIME__ << endl; + if(par.exist("version")){ + cout << white << "随机事件墙版本:" << RANDOMEVENTWALL_VERSION << endl; + cout << white << "pvzclass版本:" << pvz->Version << endl; + return 0; + } + //启动时的输出 + if (!par.exist("hide-banner")) { + cout << yellow << "===植物大战僵尸 随机事件墙===" << endl; + cout << yellow << "===by 快乐的我531/hallo1===" << endl; + cout << green << "随机事件墙版本:" << RANDOMEVENTWALL_VERSION << endl; + cout << green << "pvzclass版本:" << pvz->Version << endl; + cout << green << "编译时间: " << __DATE__ << " " << __TIME__ << endl; + }; + + if (par.exist("list-events")) { + cout << yellow << "全部事件列表:" << endl; + for (int i = 0; i < length(rew.randomEvents); i++) { + cout << white << i + 1 << ":" << rew.randomEvents[i].name << endl; + }; + return 0; + }; Creater::AsmInit(); @@ -64,18 +101,31 @@ int main() { getchar(); return 2; }; - cout << green << "游戏版本:" << PVZVersion::ToString(pvz->GameVersion)<< endl; + cout << green << "游戏版本:" << PVZVersion::ToString(pvz->GameVersion) << endl; + + if (pvz->GameVersion != PVZVersion::V1_0_0_1051) { + cout << red << "警告:该游戏版本不受支持,请使用v1.0.0.1051版本!" << endl; + }; + if (pvz->GameState != PVZGameState::Playing) { cout << white << "等待进入游戏.." << endl; } while (pvz->GameState != PVZGameState::Playing) { Sleep(200); - } + }; + + mt19937rng.seed(chrono::system_clock::now().time_since_epoch().count()); + + //现在已经进入游戏了 + if(testEvent){ + cout<BaseAddress) { e.Run(); }; diff --git a/randomEventWall/randomEventWall.cpp b/randomEventWall/randomEventWall.cpp new file mode 100644 index 0000000..572a351 --- /dev/null +++ b/randomEventWall/randomEventWall.cpp @@ -0,0 +1,93 @@ +#include +#include "include/randomEventWall.h" +#include "include/logger.h" +#include "../pvzclass/pvzclass/Enums/ZombieType.h" +#include "include/main.h" + +randomEventWall::randomEventWall(/* args */) {} +randomEventWall::~randomEventWall() {} + +bool randomEventWall::addSun_() { + //随机给予玩家100~600阳光,并且尾数总为0 + uniform_int_distribution<> rint(10,60); + unsigned int randomSun = rint(mt19937rng) * 10; + pvz->Sun = pvz->Sun + randomSun; + cout << white << "随机事件墙:获得了" << randomSun << "点阳光" << endl; + //总是成功 + return 1; +}; + +bool randomEventWall::removeSun_() { + //随机扣除玩家100~600阳光 + uniform_int_distribution<> rint(10,60); + unsigned int curSun = pvz->Sun; + if (curSun <= 100) return 0; + unsigned int randomSun; + do { + randomSun = rint(mt19937rng) * 10; + } while (randomSun >= curSun); //阳光不应该扣到负数(虽然是可以做到的) + pvz->Sun = curSun - randomSun; + cout << white << "随机事件墙:扣除了" << randomSun << "点阳光" << endl; + return 1; +}; + +//反转阳光数值,例如:520->052 +bool randomEventWall::reverseSun_() { + unsigned int curSun = pvz->Sun; + string curSunStr = to_string(curSun); + reverse(curSunStr.begin(), curSunStr.end()); + pvz->Sun = atoi(curSunStr.c_str()); + cout << white << "随机事件墙:阳光由" << curSun << "反转至" << curSunStr << endl; + return 1; +}; + +//在最右端生成1~4个普通僵尸 +bool randomEventWall::addSomeNormalZombiesAtStartLine_() { + //没错,普通僵尸->普通僵尸,路障僵尸,小鬼僵尸 + uniform_int_distribution<> rint(0, 2); + uniform_int_distribution<> rint2(0, 5); + const ZombieType::ZombieType allowedZombies[] = { + ZombieType::Zombie, ZombieType::ConeheadZombie, ZombieType::Imp}; + //生成1~3个 + int spawnCnt = rint(mt19937rng) + 1; + for (int i = 0; i < spawnCnt; i++) { + ZombieType::ZombieType randomZombie = allowedZombies[rint(mt19937rng)]; + int row = rint2(mt19937rng); + Creater::CreateZombie(randomZombie, row, 10); + if (logLevel >= LOG_DEBUG) + cout << blue << "随机事件墙:在" << row << "行最右端生成了" << ZombieType::ToString(randomZombie) << endl; + }; + cout << white << "随机事件墙:在最右端生成了" << spawnCnt << "个普通僵尸"; + return 1; +}; + +//同上,但是这次范围为正态分布 +bool randomEventWall::addSomeNormalZombiesInLawn_() { + //没错,普通僵尸->普通僵尸,路障僵尸,小鬼僵尸 + uniform_int_distribution<> rint(0, 2); + uniform_int_distribution<> rint2(0, 5); + normal_distribution rnorm(6,1.7); + const ZombieType::ZombieType allowedZombies[] = { + ZombieType::Zombie, ZombieType::ConeheadZombie, ZombieType::Imp}; + //生成1~3个 + int spawnCnt = rint(mt19937rng) + 1; + for (int i = 0; i < spawnCnt; i++) { + ZombieType::ZombieType randomZombie = allowedZombies[rint(mt19937rng)]; + int row = rint2(mt19937rng); + int col; + do{ + col=(int)rnorm(mt19937rng); + }while(col<2||col>10); //不会贴脸刷怪 + Creater::CreateZombie(randomZombie, row, col); + if (logLevel >= LOG_DEBUG) + cout << blue << "随机事件墙:在" << row << "行"<Type == PlantType::Wallnut) { srand(GetTickCount()); + //注意:从模仿者开始的植物都不是正常植物 + uniform_int_distribution<> rint(0,PlantType::CobCannon); int spawnIncomplete=1; do{ - PlantType::PlantType randomPlant =(PlantType::PlantType)((rand() % (PlantType::LeftRepeater + 1))); - if(randomPlant==PlantType::Imitater) continue; //生成模仿者会造成游戏崩溃 + PlantType::PlantType randomPlant =(PlantType::PlantType)rint(mt19937rng); Plant* createdPlant=Creater::CreatePlant(randomPlant, brokenPlant->Row, brokenPlant->Column); createdPlant->Sleeping=false; if (logLevel >= LOG_INFO) cout << blue << "随机墙:生成了" << PlantType::ToString(randomPlant)<< endl; From a5a727d66f6224a6cc613f7bfd26a007434b8fb8 Mon Sep 17 00:00:00 2001 From: happyme531 <2302004040@qq.com> Date: Fri, 1 May 2020 20:25:53 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E9=9A=8F=E6=9C=BA=E4=BA=8B=E4=BB=B6?= =?UTF-8?q?=E5=A2=99=E7=8E=B0=E5=9C=A8=E5=8F=AF=E7=94=A8=EF=BC=8C11?= =?UTF-8?q?=E4=B8=AA=E9=9A=8F=E6=9C=BA=E4=BA=8B=E4=BB=B6=20=E9=9A=8F?= =?UTF-8?q?=E6=9C=BA=E7=AE=97=E6=B3=95=E6=94=B9=E5=8F=98=20=E5=90=84?= =?UTF-8?q?=E7=A7=8D=E4=BB=A3=E7=A0=81=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 3 +- CMakeLists.txt | 5 +- randomEventWall/include/logger.h | 55 +++++- randomEventWall/include/randomEventWall.h | 114 ++++++++--- randomEventWall/main.cpp | 36 +++- randomEventWall/randomEventWall.cpp | 112 +++-------- randomEventWall/randomEvents.cpp | 225 ++++++++++++++++++++++ randomEventWall/randomPlantWall.cpp | 10 +- 8 files changed, 426 insertions(+), 134 deletions(-) create mode 100644 randomEventWall/randomEvents.cpp diff --git a/.vscode/settings.json b/.vscode/settings.json index 48ff785..c6ab46d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -59,6 +59,7 @@ "xtree": "cpp", "xutility": "cpp", "random": "cpp", - "chrono": "cpp" + "chrono": "cpp", + "thread": "cpp" } } \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 6cbe3c2..6f32423 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,12 +4,13 @@ project(pvz-randomEventWall) set (pvz-randomEventWall_VERSION_MAJOR 0) set (pvz-randomEventWall_VERSION_MINOR 1) set(CMAKE_CXX_FLAGS "/std:c++latest ${CMAKE_CXX_FLAGS}") +SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /MANIFESTUAC:level='requireAdministrator'") configure_file( "${PROJECT_SOURCE_DIR}/randomEventWall/include/config.h.in" "${pvz-randomEventWall_BINARY_DIR}/randomEventWall/config.h" ) -aux_source_directory(./randomEventWall DIR_SRCS) +aux_source_directory(./randomEventWall/ DIR_SRCS) aux_source_directory(./randomEventWall/include DIR_SRCS) aux_source_directory(./randomEventWall/components DIR_SRCS) aux_source_directory(./randomEventWall/components/include DIR_SRCS) @@ -27,5 +28,7 @@ add_library (libpvzclass STATIC ${DIR_LIB_SRCS}) set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) add_executable(pvz-randomEventWall ${DIR_SRCS}) + + target_link_libraries(pvz-randomEventWall libpvzclass) diff --git a/randomEventWall/include/logger.h b/randomEventWall/include/logger.h index 2502d52..5a6e0ce 100644 --- a/randomEventWall/include/logger.h +++ b/randomEventWall/include/logger.h @@ -1,15 +1,59 @@ #pragma once #include +#include #include +#include +#define _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING +#include -#define LOG_VERBOSE 5 -#define LOG_DEBUG 4 -#define LOG_INFO 3 -#define LOG_WARN 2 -#define LOG_ERROR 1 +#define LOGLEVEL_VERBOSE 5 +#define LOGLEVEL_DEBUG 4 +#define LOGLEVEL_INFO 3 +#define LOGLEVEL_WARN 2 +#define LOGLEVEL_ERROR 1 + +#define LOG_VERBOSE(a) if(logLevel>=LOGLEVEL_VERBOSE){a;} +#define LOG_DEBUG(a) if(logLevel>=LOGLEVEL_DEBUG){a;} +#define LOG_INFO(a) if(logLevel>=LOGLEVEL_INFO){a;} +#define LOG_WARN(a) if(logLevel>=LOGLEVEL_WARN){a;} +#define LOG_ERROR(a) if(logLevel>=LOGLEVEL_ERROR){a;} extern int logLevel; + +//字符编码转换,STL YES! +static std::string utf8_to_gbk(const std::string& str) +{ + std::wstring_convert > conv; + std::wstring tmp_wstr = conv.from_bytes(str); + + //GBK locale name in windows + const char* GBK_LOCALE_NAME = ".936"; + std::wstring_convert> convert(new std::codecvt_byname(GBK_LOCALE_NAME)); + return convert.to_bytes(tmp_wstr); +}; + +//extern PVZ* pvz; +//游戏内输出 +struct inGameCenterCaption +{ + std::stringstream ss; + template + inGameCenterCaption & operator << (const T &data){ + ss << data; + PVZ::Caption* cap = pvz->GetCaption(); + std::string testStr = ss.str(); + std::string res; + res = utf8_to_gbk(testStr); + cap->Style = CaptionStyle::Center; + cap->DisappearCountdown = 200; + cap->SetText(res.c_str()); + return *this; + } + operator std::string() { return ss.str(); } +}; + +//彩色终端输出 inline std::ostream& blue(std::ostream &s) { HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); @@ -39,6 +83,7 @@ inline std::ostream& yellow(std::ostream &s) HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleTextAttribute(hStdout, FOREGROUND_GREEN|FOREGROUND_RED|FOREGROUND_INTENSITY); + return s; } diff --git a/randomEventWall/include/randomEventWall.h b/randomEventWall/include/randomEventWall.h index fe9ff1f..f788b9c 100644 --- a/randomEventWall/include/randomEventWall.h +++ b/randomEventWall/include/randomEventWall.h @@ -1,77 +1,127 @@ #pragma once #include +#include #include "main.h" -typedef struct randomEvent { - //该事件的幸运程度 - int luck; - //事件名 - string name; - //触发该事件对应的函数 - bool (*trigger)(void); -} randomEvent_t; +class randomEventWall; + +namespace randomEvents { +bool addSun_(randomEventWall* rew); +bool removeSun_(randomEventWall* rew); +bool reverseSun_(randomEventWall* rew); +bool addSomeNormalZombiesAtStartLine_(randomEventWall* rew); +bool addSomeNormalZombiesInLawn_(randomEventWall* rew); +bool removeSomeZombiesInLawn_(randomEventWall* rew); +bool addABalloonZombie_(randomEventWall* rew); +bool generateARandomPlant_(randomEventWall* rew); +bool generateRandomPlants_(randomEventWall* rew); +bool generateRandomPlantsInRow_(randomEventWall* rew); +bool generateRandomPlantsInColumn_(randomEventWall* rew); +}; // namespace randomEvents class randomEventWall { public: randomEventWall(/* args */); ~randomEventWall(); - void trigger(Plant* brokenPlant); + bool trigger(); + bool triggerTargetEvent(int event); + unsigned int triggeredEventId; + vector runningEvents; - private: - static bool addSun_(); - static bool removeSun_(); - static bool reverseSun_(); - static bool addSomeNormalZombiesAtStartLine_(); - static bool addSomeNormalZombiesInLawn_(); - static bool removeSomeZombiesInLawn_(); - static bool addABalloonZombie_(); + typedef struct randomEvent { + //该事件的幸运程度 + short luck; + //优先级倒数:eg.为2的优先级减半 + float priorityDen; + //事件名 + string name; + //触发该事件对应的函数 + bool (*trigger)(randomEventWall* rew); + } randomEvent_t; public: //下面是所有的随机事件 - const randomEvent_t addSun = { - .luck = 30, .name = "添加随机阳光", .trigger = &addSun_}; + + const randomEvent_t addSun = {.luck = 30, + .priorityDen = 1, + .name = "添加随机阳光", + .trigger = &randomEvents::addSun_}; const randomEvent_t removeSun = { - .luck = -30, .name = "扣除随机阳光", .trigger = &removeSun_}; + .luck = -30, + .priorityDen = 1, + .name = "扣除随机阳光", + .trigger = &randomEvents::removeSun_ + }; const randomEvent_t reverseSun = { - .luck = -20, .name = "反转阳光数值", .trigger = &reverseSun_}; + .luck = -20, + .priorityDen = 1.5, + .name = "反转阳光数值", + .trigger = &randomEvents::reverseSun_ + }; const randomEvent_t addSomeNormalZombiesAtStartLine = { .luck = -12, + .priorityDen = 1, .name = "在起点生成一些普通僵尸", - .trigger = &addSomeNormalZombiesAtStartLine_}; + .trigger = &randomEvents::addSomeNormalZombiesAtStartLine_ + }; const randomEvent_t addSomeNormalZombiesInLawn{ .luck = -17, + .priorityDen = 1, .name = "在场景中靠右生成一些普通僵尸", - .trigger = &addSomeNormalZombiesInLawn_}; + .trigger = &randomEvents::addSomeNormalZombiesInLawn_ + }; const randomEvent_t removeSomeZombiesInLawn{ .luck = 20, + .priorityDen = 1, .name = "移除场景内一些僵尸", - .trigger = &removeSomeZombiesInLawn_}; + .trigger = &randomEvents::removeSomeZombiesInLawn_}; const randomEvent_t addABalloonZombie{ .luck = -70, + .priorityDen = 1, .name = "生成一个气球僵尸", - .trigger = &addABalloonZombie_}; - randomEvent_t generateRandomPlants; - randomEvent_t generateRandomPlantsInRow; - randomEvent_t generateRandomPlantsInColumn; + .trigger = &randomEvents::addABalloonZombie_}; + const randomEvent_t generateARandomPlant{ + .luck = 22, + .priorityDen = 1.5, + .name = "生成一个随机植物", + .trigger = &randomEvents::generateARandomPlant_}; + const randomEvent_t generateRandomPlants{ + .luck = 34, + .priorityDen = 1.5, + .name = "生成一些随机植物", + .trigger = &randomEvents::generateRandomPlants_}; + const randomEvent_t generateRandomPlantsInRow{ + .luck = 60, + .priorityDen = 2, + .name = "生成一行随机植物", + .trigger = &randomEvents::generateRandomPlantsInRow_}; + const randomEvent_t generateRandomPlantsInColumn{ + .luck = 60, + .priorityDen = 2, + .name = "生成一列随机植物", + .trigger = &randomEvents::generateRandomPlantsInColumn_}; + /* randomEvent_t removePlants; randomEvent_t removePlantsInRow; randomEvent_t removePlantsInColumn; randomEvent_t launchAllLawnMovers; randomEvent_t resetAllLawnMovers; - - randomEvent_t (randomEvents[15]) = {addSun, +*/ + randomEvent_t (randomEvents[11]) = {addSun, removeSun, reverseSun, addSomeNormalZombiesAtStartLine, addSomeNormalZombiesInLawn, removeSomeZombiesInLawn, addABalloonZombie, + generateARandomPlant, generateRandomPlants, generateRandomPlantsInRow, - generateRandomPlantsInColumn, + generateRandomPlantsInColumn/*, removePlants, removePlantsInRow, removePlantsInColumn, launchAllLawnMovers, - resetAllLawnMovers}; + resetAllLawnMovers*/ + }; }; diff --git a/randomEventWall/main.cpp b/randomEventWall/main.cpp index 2dace9b..8052c21 100644 --- a/randomEventWall/main.cpp +++ b/randomEventWall/main.cpp @@ -5,13 +5,17 @@ #include "components/include/cmdline.h" #include "../pvzclass/pvzclass/utils.h" +#include "../pvzclass/pvzclass/Enums/CaptionStyle.h" #define RANDOMEVENTWALL_VERSION 0.1 using namespace std; -int logLevel = 5; +int logLevel = 5; +int testEvent=0; +bool disableRandomWall=false; +bool disableRandomEventWall=false; PVZ* pvz = nullptr; mt19937 mt19937rng(0); randomPlantWall rpw; @@ -25,14 +29,15 @@ int length(T& arr) void onPlantRemove(Event* e) { Plant* plant = ((EventPlantRemove*)e)->plant; - rpw.trigger(plant); + if (plant->Type == PlantType::Wallnut && !disableRandomWall) rpw.trigger(plant); + if (plant->Type == PlantType::Sunshroon && !disableRandomEventWall) rew.trigger(); }; //经典的随机事件墙关卡:向日葵,荷叶,随机墙,随机事件墙 //(向日葵,荷叶,坚果墙,阳光菇) void initClassicRandomWall() { - if (logLevel >= LOG_INFO) cout << blue << "修改植物卡槽.." << endl; + if (logLevel >= LOGLEVEL_INFO) cout << blue << "修改植物卡槽.." << endl; PVZ::CardSlot* cardSlot = pvz->GetCardSlot(); cardSlot->GetCard(0)->ContentCard = CardType::Sunflower; cardSlot->GetCard(1)->ContentCard = CardType::LilyPad; @@ -45,15 +50,19 @@ void initClassicRandomWall() { Utils::SetPlantCost(PlantType::Wallnut, 150); }; -int testEvent=0; int main(int argc, char* argv[], char* env[]) { + //解决中文乱码问题..? + SetConsoleOutputCP(65001); //解析参数 cmdline::parser par; par.add("version",'v',"显示程序版本"); + par.add("disable-random-event-wall",'\0',"禁用随机事件墙"); + par.add("disable-random-wall",'\0',"禁用随机(植物)墙"); par.add("hide-banner",'\0',"禁用程序启动时输出的信息"); par.add("list-events",'\0',"列出所有可用的事件(名称与id)"); - par.add("test-event",'\0',"<事件id> 执行一个事件之后退出",false,0,cmdline::range(1,length(rew.randomEvents))); par.add("log-level",'\0',"<等级> 改变日志等级(0~5)",false,5); + par.add("test-event",'\0',"<事件id> 执行一个事件之后退出",false,0,cmdline::range(1,length(rew.randomEvents))); + par.parse_check(argc,argv); testEvent=par.get("test-event"); @@ -68,6 +77,9 @@ int main(int argc, char* argv[], char* env[]) { if (!par.exist("hide-banner")) { cout << yellow << "===植物大战僵尸 随机事件墙===" << endl; cout << yellow << "===by 快乐的我531/hallo1===" << endl; + cout <Version << endl; cout << green << "编译时间: " << __DATE__ << " " << __TIME__ << endl; @@ -81,6 +93,9 @@ int main(int argc, char* argv[], char* env[]) { return 0; }; + disableRandomWall=par.exist("disable-random-wall"); + disableRandomEventWall=par.exist("disable-random-event-wall"); + Creater::AsmInit(); DWORD pid = ProcessOpener::Open(); @@ -102,7 +117,7 @@ int main(int argc, char* argv[], char* env[]) { return 2; }; - cout << green << "游戏版本:" << PVZVersion::ToString(pvz->GameVersion) << endl; + if (!par.exist("hide-banner")) cout << green << "游戏版本:" << PVZVersion::ToString(pvz->GameVersion) << endl; if (pvz->GameVersion != PVZVersion::V1_0_0_1051) { cout << red << "警告:该游戏版本不受支持,请使用v1.0.0.1051版本!" << endl; @@ -115,12 +130,15 @@ int main(int argc, char* argv[], char* env[]) { Sleep(200); }; - mt19937rng.seed(chrono::system_clock::now().time_since_epoch().count()); + mt19937rng.seed((unsigned int)chrono::system_clock::now().time_since_epoch().count()); + //现在已经进入游戏了 if(testEvent){ cout< #include "include/randomEventWall.h" #include "include/logger.h" #include "../pvzclass/pvzclass/Enums/ZombieType.h" @@ -7,87 +6,40 @@ randomEventWall::randomEventWall(/* args */) {} randomEventWall::~randomEventWall() {} -bool randomEventWall::addSun_() { - //随机给予玩家100~600阳光,并且尾数总为0 - uniform_int_distribution<> rint(10,60); - unsigned int randomSun = rint(mt19937rng) * 10; - pvz->Sun = pvz->Sun + randomSun; - cout << white << "随机事件墙:获得了" << randomSun << "点阳光" << endl; - //总是成功 - return 1; -}; - -bool randomEventWall::removeSun_() { - //随机扣除玩家100~600阳光 - uniform_int_distribution<> rint(10,60); - unsigned int curSun = pvz->Sun; - if (curSun <= 100) return 0; - unsigned int randomSun; - do { - randomSun = rint(mt19937rng) * 10; - } while (randomSun >= curSun); //阳光不应该扣到负数(虽然是可以做到的) - pvz->Sun = curSun - randomSun; - cout << white << "随机事件墙:扣除了" << randomSun << "点阳光" << endl; - return 1; -}; - -//反转阳光数值,例如:520->052 -bool randomEventWall::reverseSun_() { - unsigned int curSun = pvz->Sun; - string curSunStr = to_string(curSun); - reverse(curSunStr.begin(), curSunStr.end()); - pvz->Sun = atoi(curSunStr.c_str()); - cout << white << "随机事件墙:阳光由" << curSun << "反转至" << curSunStr << endl; - return 1; -}; +template +int length(T& arr) +{ + return sizeof(arr) / sizeof(arr[0]); +} -//在最右端生成1~4个普通僵尸 -bool randomEventWall::addSomeNormalZombiesAtStartLine_() { - //没错,普通僵尸->普通僵尸,路障僵尸,小鬼僵尸 - uniform_int_distribution<> rint(0, 2); - uniform_int_distribution<> rint2(0, 5); - const ZombieType::ZombieType allowedZombies[] = { - ZombieType::Zombie, ZombieType::ConeheadZombie, ZombieType::Imp}; - //生成1~3个 - int spawnCnt = rint(mt19937rng) + 1; - for (int i = 0; i < spawnCnt; i++) { - ZombieType::ZombieType randomZombie = allowedZombies[rint(mt19937rng)]; - int row = rint2(mt19937rng); - Creater::CreateZombie(randomZombie, row, 10); - if (logLevel >= LOG_DEBUG) - cout << blue << "随机事件墙:在" << row << "行最右端生成了" << ZombieType::ToString(randomZombie) << endl; - }; - cout << white << "随机事件墙:在最右端生成了" << spawnCnt << "个普通僵尸"; - return 1; +bool randomEventWall::triggerTargetEvent(int event) { + inGameCenterCaption() << this->randomEvents[event - 1].name; + this->triggeredEventId = event; + return this->randomEvents[event - 1].trigger(this); }; -//同上,但是这次范围为正态分布 -bool randomEventWall::addSomeNormalZombiesInLawn_() { - //没错,普通僵尸->普通僵尸,路障僵尸,小鬼僵尸 - uniform_int_distribution<> rint(0, 2); - uniform_int_distribution<> rint2(0, 5); - normal_distribution rnorm(6,1.7); - const ZombieType::ZombieType allowedZombies[] = { - ZombieType::Zombie, ZombieType::ConeheadZombie, ZombieType::Imp}; - //生成1~3个 - int spawnCnt = rint(mt19937rng) + 1; - for (int i = 0; i < spawnCnt; i++) { - ZombieType::ZombieType randomZombie = allowedZombies[rint(mt19937rng)]; - int row = rint2(mt19937rng); - int col; - do{ - col=(int)rnorm(mt19937rng); - }while(col<2||col>10); //不会贴脸刷怪 - Creater::CreateZombie(randomZombie, row, col); - if (logLevel >= LOG_DEBUG) - cout << blue << "随机事件墙:在" << row << "行"< weights; + double weightSum=0; + int eventCnt=length(this->randomEvents); + for(int i=0;irandomEvents[i].luck))); + thisWeight /= this->randomEvents[i].priorityDen; + weights.push_back(thisWeight); + weightSum += thisWeight; }; - cout << white << "随机事件墙:在场景中生成了" << spawnCnt << "个普通僵尸"; - return 1; - }; - -bool randomEventWall::removeSomeZombiesInLawn_() { - - return 1; + uniform_real_distribution ran(0, weightSum); + double target = ran(mt19937rng); + double target_original=target; + int i=0; + for (i = 0; i < eventCnt; i++){ + if(weights[i]>target) break; + target-=weights[i]; }; -bool randomEventWall::addABalloonZombie_() { return 1; }; + LOG_VERBOSE(cout<triggerTargetEvent(i+1); +}; \ No newline at end of file diff --git a/randomEventWall/randomEvents.cpp b/randomEventWall/randomEvents.cpp new file mode 100644 index 0000000..39e934f --- /dev/null +++ b/randomEventWall/randomEvents.cpp @@ -0,0 +1,225 @@ +#include "include/logger.h" +#include "include/main.h" +#include +#include +#include "include/randomEventWall.h" + +using namespace randomEvents; +using namespace std; + +namespace randomEvents { + +bool addSun_(randomEventWall* rew) { + rew->triggeredEventId = 0; + //随机给予玩家100~600阳光,并且尾数总为0 + uniform_int_distribution<> rint(10, 60); + unsigned int randomSun = rint(mt19937rng) * 10; + pvz->Sun = pvz->Sun + randomSun; + cout << white << "随机事件墙:获得了" << randomSun << "点阳光" << endl; + //总是成功 + return 1; +}; + +bool removeSun_(randomEventWall* rew) { + rew->triggeredEventId = 0; + //随机扣除玩家100~600阳光 + uniform_int_distribution<> rint(10, 60); + unsigned int curSun = pvz->Sun; + if (curSun <= 100) return 0; + unsigned int randomSun; + do { + randomSun = rint(mt19937rng) * 10; + } while (randomSun >= curSun); //阳光不应该扣到负数(虽然是可以做到的) + pvz->Sun = curSun - randomSun; + cout << white << "随机事件墙:扣除了" << randomSun << "点阳光" << endl; + return 1; +}; + +//反转阳光数值,例如:520->052 +bool reverseSun_(randomEventWall* rew) { + rew->triggeredEventId = 0; + unsigned int curSun = pvz->Sun; + string curSunStr = to_string(curSun); + reverse(curSunStr.begin(), curSunStr.end()); + pvz->Sun = atoi(curSunStr.c_str()); + cout << white << "随机事件墙:阳光由" << curSun << "反转至" << curSunStr + << endl; + return 1; +}; + +//在最右端生成1~4个普通僵尸 +bool addSomeNormalZombiesAtStartLine_(randomEventWall* rew) { + //瞬间完成 + rew->triggeredEventId = 0; + //没错,普通僵尸->普通僵尸,路障僵尸,小鬼僵尸 + uniform_int_distribution<> rint(0, 2); + uniform_int_distribution<> rint2(0, 5); + const ZombieType::ZombieType allowedZombies[] = { + ZombieType::Zombie, ZombieType::ConeheadZombie, ZombieType::Imp}; + //生成1~3个 + int spawnCnt = rint(mt19937rng) + 1; + for (int i = 0; i < spawnCnt; i++) { + ZombieType::ZombieType randomZombie = allowedZombies[rint(mt19937rng)]; + int row = rint2(mt19937rng); + Creater::CreateZombie(randomZombie, row, 9); + + LOG_DEBUG(cout << blue << "随机事件墙:在" << row << "行最右端生成了" + << ZombieType::ToString(randomZombie) << endl); + }; + cout << white << "随机事件墙:在最右端生成了" << spawnCnt << "个普通僵尸"; + return 1; +}; + +//同上,但是这次范围为正态分布 +void addSomeNormalZombiesInLawn_thread(randomEventWall* rew) { + unsigned int id = rew->triggeredEventId; + rew->triggeredEventId = 0; + rew->runningEvents.push_back(id); + this_thread::sleep_for(chrono::seconds(2)); + //没错,普通僵尸->普通僵尸,路障僵尸,小鬼僵尸 + uniform_int_distribution<> rint(0, 2); + uniform_int_distribution<> rint2(0, 5); + normal_distribution rnorm(6.5F, 1.6F); + const ZombieType::ZombieType allowedZombies[] = { + ZombieType::Zombie, ZombieType::ConeheadZombie, ZombieType::Imp}; + //生成1~3个 + int spawnCnt = rint(mt19937rng) + 1; + for (int i = 0; i < spawnCnt; i++) { + ZombieType::ZombieType randomZombie = allowedZombies[rint(mt19937rng)]; + int row = rint2(mt19937rng); + int col; + do { + col = (int)rnorm(mt19937rng); + } while (col < 2 || col > 10); //不会贴脸刷怪 + Creater::CreateZombie(randomZombie, row, col); + LOG_DEBUG(cout << blue << "随机事件墙:在" << row << "行" << col + << "列生成了" << ZombieType::ToString(randomZombie) << endl); + this_thread::sleep_for(chrono::milliseconds(400)); + }; + cout << white << "随机事件墙:在场景中生成了" << spawnCnt << "个普通僵尸"; + auto iter = find(rew->runningEvents.begin(), rew->runningEvents.end(), id); + if (iter != rew->runningEvents.end()) rew->runningEvents.erase(iter); +}; + +bool addSomeNormalZombiesInLawn_(randomEventWall* rew) { + //当前有一个同样的任务正在运行 + if (find(rew->runningEvents.begin(), rew->runningEvents.end(), + rew->triggeredEventId) != rew->runningEvents.end()) { + rew->triggeredEventId = 0; + return 0; + }; + thread t(addSomeNormalZombiesInLawn_thread, rew); + t.detach(); + return 1; +}; + +bool removeSomeZombiesInLawn_(randomEventWall* rew) { + rew->triggeredEventId = 0; + Zombie* allZombies[50]; + int zombieCnt = pvz->GetAllZombies(allZombies); + if (zombieCnt < 1) return 0; + uniform_int_distribution<> rint1(1, 6); + int killCnt; + do { + killCnt = rint1(mt19937rng); + } while (killCnt > zombieCnt); + vector temp; + for (int i = 0; i < zombieCnt; i++) temp.push_back(i); + // random_shuffle在c++17中移除了 + shuffle(temp.begin(), temp.end(), mt19937rng); + for (int i = 0; i < killCnt; i++){ + allZombies[temp[i]]->State=3; //3:秒杀 + }; + cout<triggeredEventId = 0; + uniform_int_distribution<> rint(0,5); + int row=rint(mt19937rng); + Creater::CreateZombie(ZombieType::BalloonZombie,row,9); + cout<triggeredEventId = 0; + uniform_int_distribution<> rint_plant(0, PlantType::CobCannon); //植物 + uniform_int_distribution<> rint_row(0, 5); + uniform_int_distribution<> rint_column(0, 8); + //生成1个 + int row = rint_row(mt19937rng); + int col = rint_column(mt19937rng); + PlantType::PlantType rplant = (PlantType::PlantType)rint_plant(mt19937rng); + Creater::CreatePlant(rplant, row, col); + cout << blue << "随机事件墙:在" << row << "行" << col << "列生成了" << PlantType::ToString(rplant) << endl; + return 1; +}; + +bool generateRandomPlants_thread(randomEventWall* rew){ + unsigned int id = rew->triggeredEventId; + rew->triggeredEventId = 0; + rew->runningEvents.push_back(id); + this_thread::sleep_for(chrono::seconds(2)); + uniform_int_distribution<> rint_plant(0, PlantType::CobCannon); //一行或一列玉米加农炮可能不是什么好事 + uniform_int_distribution<> rint_row(0, 5); + uniform_int_distribution<> rint_column(0, 8); + uniform_int_distribution<> rint_cnt(2,6); + int spawnCnt = rint_cnt(mt19937rng); + for (int i = 0; i < spawnCnt; i++) { + int row = rint_row(mt19937rng); + int col=rint_column(mt19937rng); + PlantType::PlantType rplant = (PlantType::PlantType)rint_plant(mt19937rng); + Plant* createdPlant=Creater::CreatePlant(rplant, row, col); + if(createdPlant->Sleeping) createdPlant->Sleeping=false; + LOG_DEBUG(cout << blue << "随机事件墙:在" << row << "行" << col<< "列生成了" << PlantType::ToString(rplant) << endl); + this_thread::sleep_for(chrono::milliseconds(400)); + }; + cout << white << "随机事件墙:在场景中生成了" << spawnCnt << "个植物"; + auto iter = find(rew->runningEvents.begin(), rew->runningEvents.end(), id); + if (iter != rew->runningEvents.end()) rew->runningEvents.erase(iter); + return 1; +}; + +bool generateRandomPlants_(randomEventWall* rew){ + //当前有一个同样的任务正在运行 + if (find(rew->runningEvents.begin(), rew->runningEvents.end(), + rew->triggeredEventId) != rew->runningEvents.end()) { + rew->triggeredEventId = 0; + return 0; + }; + thread t(generateRandomPlants_thread, rew); + t.detach(); + return 1; +}; + +bool generateRandomPlantsInRow_(randomEventWall* rew) { + rew->triggeredEventId = 0; + uniform_int_distribution<> rint_plant(0, PlantType::CobCannon-1); //植物 + uniform_int_distribution<> rint_row(0, 5); + //生成1个 + int row = rint_row(mt19937rng); + PlantType::PlantType rplant = (PlantType::PlantType)rint_plant(mt19937rng); + for (int col = 0; col <= 8; col++) { + Plant* createdPlant = Creater::CreatePlant(rplant, row, col); + if (createdPlant->Sleeping) createdPlant->Sleeping = false; + }; + cout << blue << "随机事件墙:在" << row << "行生成了" << PlantType::ToString(rplant) << endl; + return 1; +}; + +bool generateRandomPlantsInColumn_(randomEventWall* rew) { + rew->triggeredEventId = 0; + uniform_int_distribution<> rint_plant(0, PlantType::CobCannon-1); //植物 + uniform_int_distribution<> rint_col(0, 8); + //生成1个 + int col = rint_col(mt19937rng); + PlantType::PlantType rplant = (PlantType::PlantType)rint_plant(mt19937rng); + for (int row = 0; row <= 5; row++){ + Plant* createdPlant = Creater::CreatePlant(rplant, row, col); + if (createdPlant->Sleeping) createdPlant->Sleeping = false; + }; + cout << blue << "随机事件墙:在" << col << "列生成了" << PlantType::ToString(rplant) << endl; + return 1; + }; +}; // namespace randomEvents diff --git a/randomEventWall/randomPlantWall.cpp b/randomEventWall/randomPlantWall.cpp index e4f49d8..4e2b258 100644 --- a/randomEventWall/randomPlantWall.cpp +++ b/randomEventWall/randomPlantWall.cpp @@ -9,18 +9,14 @@ randomPlantWall::~randomPlantWall() {} void randomPlantWall::trigger(Plant* brokenPlant){ - if (brokenPlant->Type == PlantType::Wallnut) { - srand(GetTickCount()); //注意:从模仿者开始的植物都不是正常植物 uniform_int_distribution<> rint(0,PlantType::CobCannon); int spawnIncomplete=1; - do{ + do{ PlantType::PlantType randomPlant =(PlantType::PlantType)rint(mt19937rng); Plant* createdPlant=Creater::CreatePlant(randomPlant, brokenPlant->Row, brokenPlant->Column); - createdPlant->Sleeping=false; - if (logLevel >= LOG_INFO) cout << blue << "随机墙:生成了" << PlantType::ToString(randomPlant)<< endl; + if(createdPlant->Sleeping) createdPlant->Sleeping=false; + LOG_INFO(cout << blue << "随机墙:生成了" << PlantType::ToString(randomPlant)< Date: Fri, 1 May 2020 20:26:37 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- randomEventWall/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/randomEventWall/main.cpp b/randomEventWall/main.cpp index 8052c21..3511946 100644 --- a/randomEventWall/main.cpp +++ b/randomEventWall/main.cpp @@ -7,7 +7,7 @@ #include "../pvzclass/pvzclass/utils.h" #include "../pvzclass/pvzclass/Enums/CaptionStyle.h" -#define RANDOMEVENTWALL_VERSION 0.1 +#define RANDOMEVENTWALL_VERSION 0.2 using namespace std;