Skip to content

Commit

Permalink
Merge pull request #112 from asdawej/dev-MapGenerator
Browse files Browse the repository at this point in the history
feat: ✨ create dir for MapGenerator
  • Loading branch information
shangfengh authored Mar 6, 2024
2 parents b56afeb + 237882a commit 2f87147
Show file tree
Hide file tree
Showing 25 changed files with 331 additions and 146 deletions.
115 changes: 98 additions & 17 deletions logic/GameClass/GameObj/Map/MapStruct.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,30 @@
using Preparation.Utility;
using System;
using System.IO;

namespace GameClass.MapGenerator;

#region 异常
public class MapFileError(string filename) : Exception
{
public override string Message => $"{filename} is illegal map file";
}

public class MapStreamError(Stream str) : Exception
{
public override string Message => $"{str.ToString} is illegal stream of map";
}
#endregion

/// <summary>
/// 地图结构体
/// </summary>
public struct MapStruct
public readonly struct MapStruct
{
public uint height;
public uint width;
public PlaceType[,] map;
public readonly uint height;
public readonly uint width;
public readonly PlaceType[,] map;

#region ctor
public MapStruct(uint height, uint width)
{
Expand All @@ -34,30 +48,40 @@ public MapStruct(uint height, uint width, uint[,] map)
}
}
#endregion

#region 文件读写
/// <summary>
/// 地图文件读取
/// </summary>
/// <param name="filename">地图文件</param>
/// <returns></returns>
/// <param name="filename">待读取地图文件</param>
/// <returns>读取得到的地图</returns>
/// <exception cref="MapFileError"></exception>
public static MapStruct FromFile(string filename)
{
using BinaryReader br = new(File.OpenRead(filename));
var height = br.ReadUInt32(); var width = br.ReadUInt32();
MapStruct ret = new(height, width);
for (uint i = 0; i < height; i++)
try
{
for (uint j = 0; j < width; j++)
var height = br.ReadUInt32(); var width = br.ReadUInt32();
MapStruct ret = new(height, width);
for (uint i = 0; i < height; i++)
{
ret.map[i, j] = (PlaceType)br.ReadUInt32();
for (uint j = 0; j < width; j++)
{
ret[i, j] = (PlaceType)br.ReadUInt32();
}
}
return ret;
}
catch
{
throw new MapFileError(filename);
}
return ret;
}
/// <summary>
/// 地图文件存储
/// </summary>
/// <param name="filename">地图文件</param>
/// <param name="src">地图</param>
/// <param name="filename">待写入地图文件</param>
/// <param name="src">待写入地图</param>
public static void ToFile(string filename, MapStruct src)
{
using BinaryWriter bw = new(File.OpenWrite(filename));
Expand All @@ -67,18 +91,75 @@ public static void ToFile(string filename, MapStruct src)
{
for (uint j = 0; j < src.width; j++)
{
bw.Write((uint)src.map[i, j]);
bw.Write((uint)src[i, j]);
}
}
}
public void Clear()
#endregion

#region 流读写
/// <summary>
/// 字节提取
/// </summary>
/// <param name="str">字节输出流</param>
/// <returns>提取得到的地图</returns>
/// <exception cref="MapStreamError"></exception>
public static MapStruct FromBytes(Stream str)
{
if (!str.CanRead) throw new MapStreamError(str);
try
{
BinaryReader br = new(str);
var height = br.ReadUInt32(); var width = br.ReadUInt32();
MapStruct ret = new(height, width);
for (uint i = 0; i < height; i++)
{
for (uint j = 0; j < width; j++)
{
ret[i, j] = (PlaceType)br.ReadUInt32();
}
}
return ret;
}
catch
{
throw new MapStreamError(str);
}
}
/// <summary>
/// 字节解析
/// </summary>
/// <param name="str">字节输入流</param>
/// <param name="src">待解析地图</param>
/// <exception cref="MapStreamError"></exception>
public static void ToBytes(Stream str, MapStruct src)
{
if (!str.CanWrite) throw new MapStreamError(str);
BinaryWriter bw = new(str);
bw.Write(src.height);
bw.Write(src.width);
for (uint i = 0; i < src.height; i++)
{
for (uint j = 0; j < src.width; j++)
{
bw.Write((uint)src[i, j]);
}
}
}
#endregion

/// <summary>
/// 地图清空
/// </summary>
public readonly void Clear()
{
for (uint i = 0; i < height; i++)
{
for (uint j = 0; j < width; j++) map[i, j] = PlaceType.Null;
}
}
public PlaceType this[uint i, uint j]

public readonly PlaceType this[uint i, uint j]
{
get => map[i, j];
set => map[i, j] = value;
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
3 changes: 2 additions & 1 deletion dependency/MapGenerator-Python/.gitignore → map-generator/Python/.gitignore
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.vscode/
*.map
build/
dist/
dist/
*__pycache__
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@
r'../../logic/Preparation/bin/Release/net8.0/',
r'../../../logic/Preparation/bin/Debug/net8.0/',
r'../../../logic/Preparation/bin/Release/net8.0/',
r'_internal/']
r'./',
r'./_internal/']
PREPARATION = 'Preparation'
GAMECLASS_IMPORT = [r'../../logic/GameClass/bin/Debug/net8.0/',
r'../../logic/GameClass/bin/Release/net8.0/',
r'../../../logic/GameClass/bin/Debug/net8.0/',
r'../../../logic/GameClass/bin/Release/net8.0/',
r'_internal/']
r'./',
r'./_internal/']
GAMECLASS = 'GameClass'


Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from Classes.RandomCore import RandomCore


class DefaultСюйЧэнRandomSettings:
class DefaultXuchengRandomSettings:
asteroidWidth = 2
resourceNum = 7
constructionNum = 5
Expand All @@ -19,7 +19,7 @@ class DefaultСюйЧэнRandomSettings:
ruinCrossBonus = 40


class СюйЧэнRandomCore(RandomCore):
class XuchengRandomCore(RandomCore):
title: str
asteroidWidth: int
resourceNum: int
Expand All @@ -36,7 +36,7 @@ def AsteroidWidth(self) -> int:
@AsteroidWidth.setter
def AsteroidWidth(self, value: int) -> None:
if value < 1 or value > 4:
self.asteroidWidth = DefaultСюйЧэнRandomSettings.asteroidWidth
self.asteroidWidth = DefaultXuchengRandomSettings.asteroidWidth
else:
self.asteroidWidth = value

Expand All @@ -47,7 +47,7 @@ def ResourceNum(self) -> int:
@ResourceNum.setter
def ResourceNum(self, value: int) -> None:
if value < 1 or value > 10:
self.resourceNum = DefaultСюйЧэнRandomSettings.resourceNum
self.resourceNum = DefaultXuchengRandomSettings.resourceNum
else:
self.resourceNum = value

Expand All @@ -58,7 +58,7 @@ def ConstructionNum(self) -> int:
@ConstructionNum.setter
def ConstructionNum(self, value: int) -> None:
if value < 1 or value > 10:
self.constructionNum = DefaultСюйЧэнRandomSettings.constructionNum
self.constructionNum = DefaultXuchengRandomSettings.constructionNum
else:
self.constructionNum = value

Expand All @@ -69,7 +69,7 @@ def ShadowProb(self) -> float:
@ShadowProb.setter
def ShadowProb(self, value: float) -> None:
if value < 0 or value > 0.1:
self.shadowProb = DefaultСюйЧэнRandomSettings.shadowProb
self.shadowProb = DefaultXuchengRandomSettings.shadowProb
else:
self.shadowProb = value

Expand All @@ -80,7 +80,7 @@ def ShadowCrossBonus(self) -> int:
@ShadowCrossBonus.setter
def ShadowCrossBonus(self, value: int) -> None:
if value < 1 or value > 50:
self.shadowCrossBonus = DefaultСюйЧэнRandomSettings.shadowCrossBonus
self.shadowCrossBonus = DefaultXuchengRandomSettings.shadowCrossBonus
else:
self.shadowCrossBonus = value

Expand All @@ -91,7 +91,7 @@ def RuinProb(self) -> float:
@RuinProb.setter
def RuinProb(self, value: float) -> None:
if value < 0 or value > 0.1:
self.ruinProb = DefaultСюйЧэнRandomSettings.ruinProb
self.ruinProb = DefaultXuchengRandomSettings.ruinProb
else:
self.ruinProb = value

Expand All @@ -102,19 +102,19 @@ def RuinCrossBonus(self) -> int:
@RuinCrossBonus.setter
def RuinCrossBonus(self, value: int) -> None:
if value < 1 or value > 50:
self.ruinCrossBonus = DefaultСюйЧэнRandomSettings.ruinCrossBonus
self.ruinCrossBonus = DefaultXuchengRandomSettings.ruinCrossBonus
else:
self.ruinCrossBonus = value

def __init__(self,
title,
asteroidWidth: int = DefaultСюйЧэнRandomSettings.asteroidWidth,
resourceNum: int = DefaultСюйЧэнRandomSettings.resourceNum,
constructionNum: int = DefaultСюйЧэнRandomSettings.constructionNum,
shadowProb: float = DefaultСюйЧэнRandomSettings.shadowProb,
shadowCrossBonus: int = DefaultСюйЧэнRandomSettings.shadowCrossBonus,
ruinProb: float = DefaultСюйЧэнRandomSettings.ruinProb,
ruinCrossBonus: int = DefaultСюйЧэнRandomSettings.ruinCrossBonus) -> None:
asteroidWidth: int = DefaultXuchengRandomSettings.asteroidWidth,
resourceNum: int = DefaultXuchengRandomSettings.resourceNum,
constructionNum: int = DefaultXuchengRandomSettings.constructionNum,
shadowProb: float = DefaultXuchengRandomSettings.shadowProb,
shadowCrossBonus: int = DefaultXuchengRandomSettings.shadowCrossBonus,
ruinProb: float = DefaultXuchengRandomSettings.ruinProb,
ruinCrossBonus: int = DefaultXuchengRandomSettings.ruinCrossBonus) -> None:
self.title = title
self.AsteroidWidth = asteroidWidth
self.ResourceNum = resourceNum
Expand All @@ -126,7 +126,7 @@ def __init__(self,

@property
def Name(self) -> str:
return 'СюйЧэн'
return 'Xucheng'

def Menu(self) -> bool:
try:
Expand Down Expand Up @@ -163,14 +163,14 @@ def Menu(self) -> bool:

def Random(self, mp: MapStruct) -> None:
mp.Clear()
СюйЧэнRandomCore.generateBorderRuin(mp)
СюйЧэнRandomCore.generateHome(mp)
СюйЧэнRandomCore.generateAsteroid(mp, self.asteroidWidth)
СюйЧэнRandomCore.generateResource(mp, self.resourceNum)
СюйЧэнRandomCore.generateConstruction(mp, self.constructionNum)
СюйЧэнRandomCore.generateShadow(mp, self.shadowProb, self.shadowCrossBonus)
СюйЧэнRandomCore.generateRuin(mp, self.ruinProb, self.ruinCrossBonus)
СюйЧэнRandomCore.generateWormhole(mp)
XuchengRandomCore.generateBorderRuin(mp)
XuchengRandomCore.generateHome(mp)
XuchengRandomCore.generateAsteroid(mp, self.asteroidWidth)
XuchengRandomCore.generateResource(mp, self.resourceNum)
XuchengRandomCore.generateConstruction(mp, self.constructionNum)
XuchengRandomCore.generateShadow(mp, self.shadowProb, self.shadowCrossBonus)
XuchengRandomCore.generateRuin(mp, self.ruinProb, self.ruinCrossBonus)
XuchengRandomCore.generateWormhole(mp)

@staticmethod
def isEmptyNearby(mp: MapStruct, x: int, y: int, r: int) -> bool:
Expand Down Expand Up @@ -214,7 +214,7 @@ def generateHome(mp: MapStruct) -> None:
mp[46, 3] = PT.Home

@staticmethod
def generateAsteroid(mp: MapStruct, width: int = DefaultСюйЧэнRandomSettings.asteroidWidth) -> None:
def generateAsteroid(mp: MapStruct, width: int = DefaultXuchengRandomSettings.asteroidWidth) -> None:
for i in range(1, 49):
for j in range(24, 24 - width, -1):
mp[i, j] = PT.Asteroid
Expand All @@ -227,52 +227,52 @@ def generateAsteroid(mp: MapStruct, width: int = DefaultСюйЧэнRandomSettin
mp[49 - i, 25 - width] = PT.Null

@staticmethod
def generateResource(mp: MapStruct, num: int = DefaultСюйЧэнRandomSettings.resourceNum) -> None:
def generateResource(mp: MapStruct, num: int = DefaultXuchengRandomSettings.resourceNum) -> None:
i = 0
while i < num:
x = floor(random() * 48) + 1
y = floor(random() * 23) + 1
if СюйЧэнRandomCore.isEmptyNearby(mp, x, y, 2):
if XuchengRandomCore.isEmptyNearby(mp, x, y, 2):
mp[x, y] = PT.Resource
mp[49 - x, 49 - y] = PT.Resource
else:
i -= 1
i += 1

@staticmethod
def generateConstruction(mp: MapStruct, num: int = DefaultСюйЧэнRandomSettings.constructionNum) -> None:
def generateConstruction(mp: MapStruct, num: int = DefaultXuchengRandomSettings.constructionNum) -> None:
i = 0
while i < num:
x = floor(random() * 48) + 1
y = floor(random() * 23) + 1
if СюйЧэнRandomCore.isEmptyNearby(mp, x, y, 1):
if XuchengRandomCore.isEmptyNearby(mp, x, y, 1):
mp[x, y] = PT.Construction
mp[49 - x, 49 - y] = PT.Construction
else:
i -= 1
i += 1

@staticmethod
def generateShadow(mp: MapStruct, prob: float = DefaultСюйЧэнRandomSettings.shadowProb,
crossBonus: int = DefaultСюйЧэнRandomSettings.shadowCrossBonus) -> None:
def generateShadow(mp: MapStruct, prob: float = DefaultXuchengRandomSettings.shadowProb,
crossBonus: int = DefaultXuchengRandomSettings.shadowCrossBonus) -> None:
for i in range(50):
for j in range(50):
if (mp[i, j] == PT.Null and
random() < prob * (СюйЧэнRandomCore.haveSthCross(mp, i, j, 1, PT.Shadow) * crossBonus + 1)):
random() < prob * (XuchengRandomCore.haveSthCross(mp, i, j, 1, PT.Shadow) * crossBonus + 1)):
mp[i, j] = PT.Shadow
mp[49 - i, 49 - j] = PT.Shadow

@staticmethod
def generateRuin(mp: MapStruct, prob: float = DefaultСюйЧэнRandomSettings.ruinProb,
crossBonus: int = DefaultСюйЧэнRandomSettings.ruinCrossBonus) -> None:
def generateRuin(mp: MapStruct, prob: float = DefaultXuchengRandomSettings.ruinProb,
crossBonus: int = DefaultXuchengRandomSettings.ruinCrossBonus) -> None:
for i in range(2, 48):
for j in range(2, 48):
if ((mp[i, j] == PT.Null or mp[i, j] == PT.Shadow) and
not СюйЧэнRandomCore.haveSthNearby(mp, i, j, 1, PT.Asteroid) and
not СюйЧэнRandomCore.haveSthNearby(mp, i, j, 1, PT.Home) and
not XuchengRandomCore.haveSthNearby(mp, i, j, 1, PT.Asteroid) and
not XuchengRandomCore.haveSthNearby(mp, i, j, 1, PT.Home) and
random() < prob
* (СюйЧэнRandomCore.haveSthCross(mp, i, j, 1, PT.Ruin)
* (0 if СюйЧэнRandomCore.haveSthCross(mp, i, j, 1, PT.Ruin) > 1
* (XuchengRandomCore.haveSthCross(mp, i, j, 1, PT.Ruin)
* (0 if XuchengRandomCore.haveSthCross(mp, i, j, 1, PT.Ruin) > 1
else crossBonus) + 1)):
mp[i, j] = PT.Ruin
mp[49 - i, 49 - j] = PT.Ruin
Expand Down
Loading

0 comments on commit 2f87147

Please sign in to comment.