diff --git a/processor/.clang-format b/processor/.clang-format new file mode 100644 index 0000000..4a78802 --- /dev/null +++ b/processor/.clang-format @@ -0,0 +1,148 @@ +Language: Cpp +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: Left +AlignConsecutiveMacros: None +AlignConsecutiveAssignments: None +AlignConsecutiveBitFields: None +AlignConsecutiveDeclarations: None +AlignEscapedNewlines: Left +AlignOperands: Align +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortEnumsOnASingleLine: false +AllowShortBlocksOnASingleLine: Empty +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Empty +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: Yes +AttributeMacros: [] +BinPackArguments: false +BinPackParameters: false +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: false +BreakBeforeBinaryOperators: All +BreakBeforeConceptDeclarations: true +BreakBeforeBraces: Attach +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeComma +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: true +BreakConstructorInitializers: BeforeComma +BreakStringLiterals: true +ColumnLimit: 80 +QualifierAlignment: Left +CompactNamespaces: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DeriveLineEnding: true +DerivePointerAlignment: false +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: Always +ExperimentalAutoDetectBinPacking: false +PackConstructorInitializers: NextLine +ConstructorInitializerAllOnOneLineOrOnePerLine: false +AllowAllConstructorInitializersOnNextLine: false +FixNamespaceComments: true +ForEachMacros: [] +IfMacros: [] +IncludeBlocks: Merge +IndentAccessModifiers: false +IndentCaseLabels: false +IndentCaseBlocks: false +IndentGotoLabels: false +IndentPPDirectives: None +IndentExternBlock: AfterExternBlock +IndentRequires: false +IndentWidth: 4 +IndentWrappedFunctionNames: false +InsertTrailingCommas: Wrapped +InsertBraces: false +InsertNewlineAtEOF: true +KeepEmptyLinesAtTheStartOfBlocks: false +LambdaBodyIndentation: Signature +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PenaltyIndentedWhitespace: 0 +PointerAlignment: Left +PPIndentWidth: -1 +ReferenceAlignment: Pointer +ReflowComments: true +RemoveBracesLLVM: false +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SortIncludes: CaseSensitive +SortJavaStaticImport: Before +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: false +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterOverloadedOperator: false + BeforeNonEmptyParentheses: false +SpaceAroundPointerQualifiers: Default +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: Never +SpacesInConditionalStatement: false +SpacesInContainerLiterals: false +SpacesInCStyleCastParentheses: false +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +BitFieldColonSpacing: Both +Standard: Latest +TabWidth: 4 +UseCRLF: false +UseTab: Always + diff --git a/processor/logic/terrain.cpp b/processor/logic/terrain.cpp index 3fa15ad..b2fef20 100644 --- a/processor/logic/terrain.cpp +++ b/processor/logic/terrain.cpp @@ -1,194 +1,280 @@ #include "terrain.h" -#include #include #include - +#include using namespace std; -BadImportTerrainConfig::BadImportTerrainConfig(size_t pt):pt(pt){} +BadImportTerrainConfig::BadImportTerrainConfig(size_t pt): pt(pt) {} -const char* BadImportTerrainConfig::what() const noexcept{ - return ("ImportTerrainConfig "+to_string(pt)).c_str(); +const char* BadImportTerrainConfig::what() const noexcept { + return ("ImportTerrainConfig " + to_string(pt)).c_str(); } -const char* BadCapitalAssign::what() const noexcept{ - return "Bad Capital Assign"; +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}; - } +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; } -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 +void upmin(T& x, const T& y) { + if (y < x) + x = y; } -ImportedTerrain importTerrain(const ImportTerrainConfig &in){ - ImportedTerrain t; - t.w=in.w,t.h=in.h; - t.tiles.resize(t.h,vector(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 +pair> 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 = false; + for (pos_t i = 0; i < h; i++) { + for (pos_t j = 0; j < w; j++) { + if (!ban(vertex_type[i][j]) && !dfn[i][j]) { + if (flag) + return false; + flag = 1, tarjan(i, j, -1, -1, 1); + } + } + } + return true; + }; + + vector 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 < h; x++) { + for (pos_t y = 0; y < w; y++) { + if (vertex_type[x][y] == VertexType::Ordinary) + options.emplace_back(x, y); + if (vertex_type[x][y] == VertexType::Cut) + vertex_type[x][y] = VertexType::Ordinary; + } + } + + if (options.empty()) + return {false, {}}; + + res[i] = options[rnd() % options.size()]; + vertex_type[res[i].x][res[i].y] = VertexType::Capital; + } + return {true, res}; +} + +} // namespace + +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 < h; i++) { + for (pos_t j = 0; j < w; j++) { + g.at(i, j).type = tiles[i][j].type; + g.at(i, j).unit = tiles[i][j].unit; + } + } + + auto arrange = [&perm, &g](const vector& 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 < C.size(); j++) + rest.push_back(players[C[j]]); + for (size_t j = 0; j < min(C.size(), D.size()); j++) { + g.at(caps[D[j]].x, caps[D[j]].y).type = TileType::Capital; + g.at(caps[D[j]].x, caps[D[j]].y).owner = players[C[j]]; + } + }; + + vector> 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 < A.size(); i++) { + for (auto id : players[A[i]]) + rest1.push_back(id); + } + + for (size_t i = 0; i < min(A.size(), B.size()); i++) + arrange(players[A[i]], capitals[B[i]], rest1); + + vector 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 < h; i++) { + for (pos_t j = 0; j < w; j++) { + if (g.at(i, j).type == TileType::Mountain) + vertex_type[i][j] = VertexType::Mountain; + if (g.at(i, j).type == TileType::Capital) + vertex_type[i][j] = VertexType::Capital; + } + } + + auto pr = generateCapital(w, h, vertex_type, rest2.size()); + if (!pr.first) + continue; + + for (size_t i = 0; i < rest2.size(); i++) { + g.at(pr.second[i].x, pr.second[i].y).type = TileType::Capital; + g.at(pr.second[i].x, pr.second[i].y).owner = rest2[i]; + } + return g; + } + + throw BadCapitalAssign(); +} + +ImportedTerrain importTerrain(const ImportTerrainConfig& in) { + ImportedTerrain t; + t.w = in.w; + t.h = in.h; + t.tiles.resize(t.h, vector(t.w)); + + size_t pt = 0; + auto error = [&]() { throw BadImportTerrainConfig(pt); }; + auto view = [&](char c) { + return pt < in.value.size() && in.value[pt] == c ? (pt++, true) : false; + }; + + auto jump = [&](char c) { + if (!view(c)) + error(); + }; + + auto read = [&](int l = -99999, int r = 99999) { + bool neg = view('-'); + if (!(pt < in.value.size() && isdigit(in.value[pt]))) + error(); + + std::int32_t x = 0; + while (pt < in.value.size() && isdigit(in.value[pt])) { + x = x * 10 + (in.value[pt] ^ '0'); + if (x > 99999) + error(); + pt++; + } + if (neg) + x = -x; + if (x < l || x > r) + error(); + return x; + }; + + vector>> vec(27, vector>(101)); + for (pos_t i = 0; i < t.h; i++) { + for (pos_t j = 0; j < t.w; j++) { + auto& p = t.tiles[i][j]; + if (view(' ')) + p.type = TileType::Blank; + else if (view('m')) + p.type = TileType::Mountain; + else if (view('n')) { + p.type = TileType::Blank; + p.unit = read(); + } else if (view('s')) + p.type = TileType::Swamp; + else if (view('g')) { + p.type = TileType::Blank; + bool tag = 1; + int team = (pt < in.value.size() && isupper(in.value[pt]) + ? in.value[pt++] - 'A' + : (tag = view(' '), 26)); + + int priority + = (tag && pt < in.value.size() && isdigit(in.value[pt]) + ? read(1, 99) + : 100); + vec[team][priority].emplace_back(i, j); + } else { + p.type = TileType::Stronghold; + p.unit = read(); + } + if (i + 1 < t.h || j + 1 < t.w) + jump(','); + } + } + + if (pt != in.value.size()) + error(); + t.capitals.emplace_back(); + + for (int i = 0; i <= 26; i++) { + for (int j = 100; j >= 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; +} diff --git a/processor/logic/terrain.h b/processor/logic/terrain.h index 85b46b7..504bc2d 100644 --- a/processor/logic/terrain.h +++ b/processor/logic/terrain.h @@ -1,42 +1,45 @@ #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 "pc/Point.h" +#include "pc/commcode.h" +#include "pc/pctypes.h" #include +#include -class BadImportTerrainConfig:std::exception{ +class BadImportTerrainConfig : std::exception { public: - BadImportTerrainConfig(size_t); - ~BadImportTerrainConfig()=default; - const char* what() const noexcept; + BadImportTerrainConfig(size_t); + virtual ~BadImportTerrainConfig() = default; + virtual const char* what() const noexcept override; + private: - size_t pt; + size_t pt; }; -class BadCapitalAssign:std::exception{ +class BadCapitalAssign : std::exception { public: - ~BadCapitalAssign()=default; - const char* what() const noexcept; + virtual ~BadCapitalAssign() = default; + virtual const char* what() const noexcept override; }; -class ImportedTerrain{ +class ImportedTerrain { public: - friend ImportedTerrain importTerrain(const ImportTerrainConfig &in); - GameBoard makeGameBoard(const InitInfo &init_info); + 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; + struct TerrainTile { + TileType type; + std::int32_t unit; + }; + pos_t w, h; + std::vector> tiles; + std::vector>> capitals; }; -ImportedTerrain importTerrain(const ImportTerrainConfig &in); +ImportedTerrain importTerrain(const ImportTerrainConfig& in); #endif +