diff --git a/processor/logic/terrain.cpp b/processor/logic/terrain.cpp new file mode 100644 index 0000000..3fa15ad --- /dev/null +++ b/processor/logic/terrain.cpp @@ -0,0 +1,194 @@ +#include "terrain.h" +#include +#include +#include + +using namespace std; + +BadImportTerrainConfig::BadImportTerrainConfig(size_t pt):pt(pt){} + +const char* BadImportTerrainConfig::what() const noexcept{ + return ("ImportTerrainConfig "+to_string(pt)).c_str(); +} + +const char* BadCapitalAssign::what() const noexcept{ + return "Bad Capital Assign"; +} + +inline namespace{ + mt19937 rnd(19260817); + enum class VertexType:std::uint8_t{ + Ordinary,Mountain,Capital,Cut + }; + bool ban(VertexType t){return t==VertexType::Mountain||t==VertexType::Capital;} + template void upmin(T &x,const T &y){if(y> generateCapital(pos_t w,pos_t h,vector> &vertex_type,int r){ + auto findCut=[&](){ + int idx=0; vector> dfn(h,vector(w)),low=dfn; + function tarjan=[&](int x,int y,int fx,int fy,bool rt){ + dfn[x][y]=low[x][y]=++idx; + int ch=0; + for(int i=0;i<4;i++){ + static const int dx[]={0,0,-1,1},dy[]={-1,1,0,0}; + const int xx=x+dx[i],yy=y+dy[i]; + if(xx<0||xx>=h||yy<0||yy>=w) continue; + if(vertex_type[xx][yy]==VertexType::Capital) vertex_type[x][y]=VertexType::Cut; + if(ban(vertex_type[xx][yy])||(xx==fx&&yy==fy)) continue; + if(!dfn[xx][yy]){ + ch++; + tarjan(xx,yy,x,y,0); + upmin(low[x][y],low[xx][yy]); + if(!rt&&low[xx][yy]>=dfn[x][y]) vertex_type[x][y]=VertexType::Cut; + } + else upmin(low[x][y],dfn[xx][yy]); + } + if(rt&&ch>=2) vertex_type[x][y]=VertexType::Cut; + }; + bool flag=0; + for(pos_t i=0;i res(r); + for(int i=0;i<=r;i++){ + if(!findCut()) return {false,vector()}; + if(i==r) break; + vector options; + for(pos_t x=0;x()}; + res[i]=options[rnd()%options.size()]; + vertex_type[res[i].x][res[i].y]=VertexType::Capital; + } + return {true,res}; + } +} + +GameBoard ImportedTerrain::makeGameBoard(const InitInfo &init_info){ + auto perm=[](std::uint8_t n){ + vector vec(n); + iota(vec.begin(),vec.end(),0); + shuffle(vec.begin(),vec.end(),rnd); + return vec; + }; + GameBoard g(w,h,init_info); + for(pos_t i=0;i &players,const vector> &capitals,vector &rest){ + vector caps; + for(const auto &v:capitals){ + for(const auto &p:v) caps.push_back(p); + if(caps.size()>=players.size()) break; + } + auto C=perm(players.size()),D=perm(caps.size()); + for(size_t j=D.size();j> players(g.numTeams()); + for(int i=1,n=g.numPlayers();i<=n;i++) + players[g.teamOf(i)-1].push_back(i); + auto A=perm(players.size()),B=perm(capitals.size()-1); + vector rest1; + for(size_t i=B.size();i rest2; + arrange(rest1,capitals.back(),rest2); + int T=5; + while(T--){ + vector> vertex_type(h,vector(w,VertexType::Ordinary)); + for(pos_t i=0;i(t.w)); + size_t pt=0; + auto error=[&](){throw BadImportTerrainConfig(pt);}; + auto view=[&](char c){return pt99999) error(); pt++; + } + if(neg) x=-x; + if(xr) error(); + return x; + }; + static vector vec[27][101]; + for(pos_t i=0;i=1;j--){ + if(!vec[i][j].empty()){ + t.capitals.back().emplace_back().swap(vec[i][j]); + } + } + if(!t.capitals.back().empty()&&i!=26){ + t.capitals.emplace_back(); + } + } + return t; +} \ No newline at end of file diff --git a/processor/logic/terrain.h b/processor/logic/terrain.h new file mode 100644 index 0000000..85b46b7 --- /dev/null +++ b/processor/logic/terrain.h @@ -0,0 +1,42 @@ +#ifndef OGLG_TERRAIN_H_ +#define OGLG_TERRAIN_H_ + +#include "pc/Point.h" +#include "pc/pctypes.h" +#include "pc/commcode.h" +#include "logic/GameBoard.h" +#include +#include + +class BadImportTerrainConfig:std::exception{ +public: + BadImportTerrainConfig(size_t); + ~BadImportTerrainConfig()=default; + const char* what() const noexcept; +private: + size_t pt; +}; + +class BadCapitalAssign:std::exception{ +public: + ~BadCapitalAssign()=default; + const char* what() const noexcept; +}; + +class ImportedTerrain{ +public: + friend ImportedTerrain importTerrain(const ImportTerrainConfig &in); + GameBoard makeGameBoard(const InitInfo &init_info); +private: + struct TerrainTile{ + TileType type; + std::int32_t unit; + }; + pos_t w,h; + std::vector> tiles; + std::vector>> capitals; +}; + +ImportedTerrain importTerrain(const ImportTerrainConfig &in); + +#endif diff --git a/processor/xmake.lua b/processor/xmake.lua index 26e3d41..10ece0d 100644 --- a/processor/xmake.lua +++ b/processor/xmake.lua @@ -4,7 +4,7 @@ set_version("0.1.0") set_languages("c++20") set_targetdir("build") -add_includedirs(".", "pc", "utility") +add_includedirs(".", "pc", "utility", "logic") add_files("pc/*.cpp", "utility/*.cpp", "logic/*.cpp") target("main")