pyscreeps-arena 0.3.6__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyscreeps-arena-0.3.6 → pyscreeps-arena-0.4.0}/PKG-INFO +9 -1
- {pyscreeps-arena-0.3.6 → pyscreeps-arena-0.4.0}/pyscreeps_arena/__init__.py +2 -1
- {pyscreeps-arena-0.3.6 → pyscreeps-arena-0.4.0}/pyscreeps_arena/compiler.py +202 -33
- {pyscreeps-arena-0.3.6 → pyscreeps-arena-0.4.0}/pyscreeps_arena/core/config.py +1 -1
- {pyscreeps-arena-0.3.6 → pyscreeps-arena-0.4.0}/pyscreeps_arena/core/const.py +3 -2
- pyscreeps-arena-0.4.0/pyscreeps_arena/project.7z +0 -0
- {pyscreeps-arena-0.3.6 → pyscreeps-arena-0.4.0}/pyscreeps_arena.egg-info/PKG-INFO +9 -1
- {pyscreeps-arena-0.3.6 → pyscreeps-arena-0.4.0}/pyscreeps_arena.egg-info/entry_points.txt +1 -0
- {pyscreeps-arena-0.3.6 → pyscreeps-arena-0.4.0}/setup.py +2 -1
- pyscreeps-arena-0.3.6/pyscreeps_arena/project.7z +0 -0
- {pyscreeps-arena-0.3.6 → pyscreeps-arena-0.4.0}/pyscreeps_arena/build.py +0 -0
- {pyscreeps-arena-0.3.6 → pyscreeps-arena-0.4.0}/pyscreeps_arena/core/__init__.py +0 -0
- {pyscreeps-arena-0.3.6 → pyscreeps-arena-0.4.0}/pyscreeps_arena/core/basic.py +0 -0
- {pyscreeps-arena-0.3.6 → pyscreeps-arena-0.4.0}/pyscreeps_arena/core/core.py +0 -0
- {pyscreeps-arena-0.3.6 → pyscreeps-arena-0.4.0}/pyscreeps_arena/core/main.py +0 -0
- {pyscreeps-arena-0.3.6 → pyscreeps-arena-0.4.0}/pyscreeps_arena/core/utils.py +0 -0
- {pyscreeps-arena-0.3.6 → pyscreeps-arena-0.4.0}/pyscreeps_arena/localization.py +0 -0
- {pyscreeps-arena-0.3.6 → pyscreeps-arena-0.4.0}/pyscreeps_arena.egg-info/SOURCES.txt +0 -0
- {pyscreeps-arena-0.3.6 → pyscreeps-arena-0.4.0}/pyscreeps_arena.egg-info/dependency_links.txt +0 -0
- {pyscreeps-arena-0.3.6 → pyscreeps-arena-0.4.0}/pyscreeps_arena.egg-info/requires.txt +0 -0
- {pyscreeps-arena-0.3.6 → pyscreeps-arena-0.4.0}/pyscreeps_arena.egg-info/top_level.txt +0 -0
- {pyscreeps-arena-0.3.6 → pyscreeps-arena-0.4.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pyscreeps-arena
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Python api|interface to play game: Screeps: Arena.
|
|
5
5
|
Author-email: 2229066748@qq.com
|
|
6
6
|
Maintainer: Eagle'sBaby
|
|
@@ -11,6 +11,14 @@ Classifier: Programming Language :: Python
|
|
|
11
11
|
Classifier: Programming Language :: Python :: 3
|
|
12
12
|
Requires-Python: >=3.10
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
|
+
Requires-Dist: pyperclip
|
|
15
|
+
Requires-Dist: colorama
|
|
16
|
+
Requires-Dist: py7zr
|
|
17
|
+
Requires-Dist: chardet
|
|
18
|
+
Requires-Dist: Transcrypt==3.9.1
|
|
19
|
+
Requires-Dist: mkdocs
|
|
20
|
+
Requires-Dist: mkdocstrings[python]
|
|
21
|
+
Requires-Dist: mkdocs-material
|
|
14
22
|
|
|
15
23
|
# PyScreeps-Arena
|
|
16
24
|
|
|
@@ -7,6 +7,7 @@ def CMD_NewProject():
|
|
|
7
7
|
"""
|
|
8
8
|
cmd:
|
|
9
9
|
pyscreeps-arena [project_path]
|
|
10
|
+
arena [project_path]
|
|
10
11
|
|
|
11
12
|
* 复制"src" "game" "build.py" 到指定目录
|
|
12
13
|
|
|
@@ -14,7 +15,7 @@ def CMD_NewProject():
|
|
|
14
15
|
|
|
15
16
|
"""
|
|
16
17
|
if len(sys.argv) < 2:
|
|
17
|
-
print("Usage: pyarena new [project_path]")
|
|
18
|
+
print("Usage: pyarena new [project_path]\n# or\narena new [project_path]")
|
|
18
19
|
return
|
|
19
20
|
project_path = sys.argv[1]
|
|
20
21
|
if not os.path.exists(project_path):
|
|
@@ -43,7 +43,7 @@ class Compiler_Const:
|
|
|
43
43
|
|
|
44
44
|
TOTAL_INSERT_AT_HEAD = """
|
|
45
45
|
import { createConstructionSite, findClosestByPath, findClosestByRange, findInRange, findPath, getCpuTime, getDirection, getHeapStatistics, getObjectById, getObjects, getObjectsByPrototype, getRange, getTerrainAt, getTicks,} from 'game/utils';
|
|
46
|
-
import { ConstructionSite, Creep, GameObject, OwnedStructure, Resource, Source, Structure, StructureContainer, StructureExtension, StructureRampart, StructureRoad, StructureSpawn, StructureWall, StructureTower} from 'game/prototypes';
|
|
46
|
+
import { ConstructionSite as GameConstructionSite, Creep as GameCreep, GameObject as GameObjectProto, OwnedStructure, Resource as GameResource, Source as GameSource, Structure as GameStructure, StructureContainer as GameStructureContainer, StructureExtension as GameStructureExtension, StructureRampart as GameStructureRampart, StructureRoad as GameStructureRoad, StructureSpawn as GameStructureSpawn, StructureWall as GameStructureWall, StructureTower as GameStructureTower} from 'game/prototypes';
|
|
47
47
|
import { ATTACK, ATTACK_POWER, BODYPART_COST, BODYPART_HITS, BOTTOM, BOTTOM_LEFT, BOTTOM_RIGHT, BUILD_POWER, CARRY, CARRY_CAPACITY, CONSTRUCTION_COST, CONSTRUCTION_COST_ROAD_SWAMP_RATIO, CONSTRUCTION_COST_ROAD_WALL_RATIO, CONTAINER_CAPACITY, CONTAINER_HITS, CREEP_SPAWN_TIME, DISMANTLE_COST, DISMANTLE_POWER, ERR_BUSY, ERR_FULL, ERR_INVALID_ARGS, ERR_INVALID_TARGET, ERR_NAME_EXISTS, ERR_NOT_ENOUGH_ENERGY, ERR_NOT_ENOUGH_EXTENSIONS, ERR_NOT_ENOUGH_RESOURCES, ERR_NOT_FOUND, ERR_NOT_IN_RANGE, ERR_NOT_OWNER, ERR_NO_BODYPART, ERR_NO_PATH, ERR_TIRED, EXTENSION_ENERGY_CAPACITY, EXTENSION_HITS, HARVEST_POWER, HEAL, HEAL_POWER, LEFT, MAX_CONSTRUCTION_SITES, MAX_CREEP_SIZE, MOVE, OBSTACLE_OBJECT_TYPES, OK, RAMPART_HITS, RAMPART_HITS_MAX, RANGED_ATTACK, RANGED_ATTACK_DISTANCE_RATE, RANGED_ATTACK_POWER, RANGED_HEAL_POWER, REPAIR_COST, REPAIR_POWER, RESOURCES_ALL, RESOURCE_DECAY, RESOURCE_ENERGY, RIGHT, ROAD_HITS, ROAD_WEAROUT, SOURCE_ENERGY_REGEN, SPAWN_ENERGY_CAPACITY, SPAWN_HITS, STRUCTURE_PROTOTYPES, TERRAIN_PLAIN, TERRAIN_SWAMP, TERRAIN_WALL, TOP, TOP_LEFT, TOP_RIGHT, TOUGH, TOWER_CAPACITY, TOWER_COOLDOWN, TOWER_ENERGY_COST, TOWER_FALLOFF, TOWER_FALLOFF_RANGE, TOWER_HITS, TOWER_OPTIMAL_RANGE, TOWER_POWER_ATTACK, TOWER_POWER_HEAL, TOWER_POWER_REPAIR, TOWER_RANGE, WALL_HITS, WALL_HITS_MAX, WORK} from 'game/constants';
|
|
48
48
|
|
|
49
49
|
import {arenaInfo} from "game";
|
|
@@ -56,27 +56,39 @@ import {searchPath, CostMatrix} from "game/path-finder"
|
|
|
56
56
|
|
|
57
57
|
TOTAL_APPEND_ATEND = """
|
|
58
58
|
export var sch = Scheduler();
|
|
59
|
-
var monitor = Monitor(
|
|
59
|
+
var monitor = Monitor(1);
|
|
60
60
|
know.now = 0;
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
_StageMachineMeta.__recursive__ = []; // 清空js首次构造时引入的数据
|
|
62
|
+
StageMachineLogicMeta.__types__ = []; // 清空js首次构造时引入的数据
|
|
64
63
|
__init_my_exists_creep_before_k__();
|
|
64
|
+
let knowCost = 0;
|
|
65
|
+
let monitorCost = 0;
|
|
66
|
+
let stepCost = 0;
|
|
67
|
+
let timeLine = 0;
|
|
65
68
|
export var loop = function () {
|
|
66
|
-
|
|
69
|
+
get.handle();
|
|
70
|
+
know.now = get.now;
|
|
71
|
+
timeLine = get.cpu_us();
|
|
67
72
|
know.handle();
|
|
73
|
+
knowCost = get.cpu_us() - timeLine;
|
|
68
74
|
if (know.now === 1) {
|
|
69
75
|
std.show_welcome();
|
|
70
76
|
init (know);
|
|
77
|
+
|
|
71
78
|
}
|
|
72
79
|
|
|
80
|
+
timeLine = get.cpu_us();
|
|
73
81
|
monitor.handle();
|
|
74
|
-
|
|
75
|
-
|
|
82
|
+
monitorCost = get.cpu_us() - timeLine;
|
|
83
|
+
for (const creep of get.creeps()){
|
|
84
|
+
creep.handle();
|
|
76
85
|
}
|
|
77
86
|
step (know);
|
|
87
|
+
timeLine = get.cpu_us();
|
|
78
88
|
sch.handle();
|
|
89
|
+
stepCost = get.cpu_us() - timeLine;
|
|
79
90
|
std.show_usage ();
|
|
91
|
+
print("knowCost:", knowCost, "monitorCost:", monitorCost, "stepCost:", stepCost);
|
|
80
92
|
};
|
|
81
93
|
"""
|
|
82
94
|
|
|
@@ -114,42 +126,70 @@ export var loop = function () {
|
|
|
114
126
|
|
|
115
127
|
ARENA_IMPORTS_GETTER = {
|
|
116
128
|
const.ARENA_GREEN: lambda: f"""
|
|
117
|
-
class
|
|
129
|
+
class GameBodyPart{{
|
|
118
130
|
constructor(){{
|
|
119
131
|
}}
|
|
120
132
|
}};
|
|
121
|
-
|
|
133
|
+
class GameAreaEffect{{
|
|
134
|
+
constructor(){{
|
|
135
|
+
}}
|
|
136
|
+
}};
|
|
137
|
+
class GameFlag{{
|
|
138
|
+
constructor(){{
|
|
139
|
+
}}
|
|
140
|
+
}};
|
|
141
|
+
const GameScoreCollector = GameStructureSpawn;
|
|
142
|
+
const RESOURCE_SCORE = "undefined";
|
|
143
|
+
const RESOURCE_SCORE_X = "undefined";
|
|
144
|
+
const RESOURCE_SCORE_Y = "undefined";
|
|
145
|
+
const RESOURCE_SCORE_Z = "undefined";
|
|
122
146
|
""",
|
|
123
147
|
const.ARENA_BLUE: lambda: f"""
|
|
124
|
-
const
|
|
125
|
-
|
|
148
|
+
const GameScoreCollector = GameStructureSpawn;
|
|
149
|
+
class GameAreaEffect{{
|
|
150
|
+
constructor(){{
|
|
151
|
+
}}
|
|
152
|
+
}};
|
|
153
|
+
const RESOURCE_SCORE = "undefined";
|
|
154
|
+
const RESOURCE_SCORE_X = "undefined";
|
|
155
|
+
const RESOURCE_SCORE_Y = "undefined";
|
|
156
|
+
const RESOURCE_SCORE_Z = "undefined";
|
|
157
|
+
import {{ Flag as GameFlag, BodyPart as GameBodyPart}} from 'arena/season_{config.season}/capture_the_flag/{"advanced" if config.level in ["advance", "advanced"] else "basic"}';
|
|
126
158
|
""",
|
|
127
159
|
const.ARENA_RED: lambda: f"""
|
|
128
|
-
class
|
|
160
|
+
class GameBodyPart{{
|
|
129
161
|
constructor(){{
|
|
130
162
|
}}
|
|
131
163
|
}};
|
|
132
|
-
|
|
164
|
+
class GameFlag{{
|
|
165
|
+
constructor(){{
|
|
166
|
+
}}
|
|
167
|
+
}};
|
|
168
|
+
import {{ ScoreCollector as GameScoreCollector, AreaEffect as GameAreaEffect, EFFECT_DAMAGE, EFFECT_FREEZE }} from 'arena/season_{config.season}/collect_and_control/{"advanced" if config.level in ["advance", "advanced"] else "basic"}';
|
|
169
|
+
|
|
170
|
+
{f"import {{ RESOURCE_SCORE_X, RESOURCE_SCORE_Y, RESOURCE_SCORE_Z }} from 'arena/season_{config.season}/collect_and_control/advanced';" if config.level in ["advance", "advanced"] else 'const RESOURCE_SCORE_X = "undefined"; const RESOURCE_SCORE_Y = "undefined"; const RESOURCE_SCORE_Z = "undefined";'}
|
|
133
171
|
|
|
134
|
-
import
|
|
135
|
-
.then((module) => {{ const RESOURCE_SCORE_X = module.RESOURCE_SCORE_X; const RESOURCE_SCORE_Y = module.RESOURCE_SCORE_Y; const RESOURCE_SCORE_Z = module.RESOURCE_SCORE_Z; }})
|
|
136
|
-
.catch((error) => {{ }});
|
|
172
|
+
{"const RESOURCE_SCORE = 'undefined';" if config.level in ["advance", "advanced"] else f"import {{ RESOURCE_SCORE }} from 'arena/season_{config.season}/collect_and_control/basic';"}
|
|
137
173
|
""",
|
|
138
174
|
const.ARENA_GRAY: lambda: f"""
|
|
139
|
-
class
|
|
175
|
+
class GameBodyPart{{
|
|
140
176
|
constructor(){{
|
|
141
177
|
}}
|
|
142
178
|
}};
|
|
143
|
-
|
|
179
|
+
class GameAreaEffect{{
|
|
180
|
+
constructor(){{
|
|
181
|
+
}}
|
|
182
|
+
}};
|
|
183
|
+
const GameScoreCollector = GameStructureSpawn;
|
|
184
|
+
const RESOURCE_SCORE_X = "undefined";
|
|
185
|
+
const RESOURCE_SCORE_Y = "undefined";
|
|
186
|
+
const RESOURCE_SCORE_Z = "undefined";
|
|
187
|
+
let GameFlag = GameStructureSpawn;
|
|
144
188
|
import("game/prototypes")
|
|
145
|
-
.then((module) => {{
|
|
146
|
-
.catch((error) => {{
|
|
189
|
+
.then((module) => {{ GameFlag = module.Flag; }})
|
|
190
|
+
.catch((error) => {{}});
|
|
147
191
|
""",
|
|
148
192
|
}
|
|
149
|
-
ARENA_IMPORTS_NOT_BLUE = ""
|
|
150
|
-
ARENA_IMPORTS_NOT_BLUE1 = """
|
|
151
|
-
import { StructureTower } from 'game/prototypes'
|
|
152
|
-
"""
|
|
153
193
|
|
|
154
194
|
|
|
155
195
|
class Compiler_Utils(Compiler_Const):
|
|
@@ -284,7 +324,7 @@ class Compiler_Utils(Compiler_Const):
|
|
|
284
324
|
return '\n'.join(result) # 将处理后的所有代码行连接成一个字符串,并返回最终结果 | join all processed lines into a string and return
|
|
285
325
|
|
|
286
326
|
def find_chain_import(self, fpath: str, search_dirs: list[str], project_path: str = None, records: dict[str, None] = None) -> list[str]:
|
|
287
|
-
"""
|
|
327
|
+
r"""
|
|
288
328
|
查找文件中的所有import语句,并返回所有import的文件路径 | find all import statements in a file and return the paths of all imported files
|
|
289
329
|
PY_IMPORT_PAT: re.compile(r'\s+from\s+(.+)(?=\s+import)\s+import\s+\*')
|
|
290
330
|
:param fpath: str 目标文件路径 | target file path
|
|
@@ -296,7 +336,7 @@ class Compiler_Utils(Compiler_Const):
|
|
|
296
336
|
if records is None:
|
|
297
337
|
records = {}
|
|
298
338
|
if not os.path.exists(fpath):
|
|
299
|
-
core.error('Compiler.find_chain_import', core.lformat(LOC_FILE_NOT_EXISTS, [fpath]), head='\n', ln=config.language)
|
|
339
|
+
core.error('Compiler.find_chain_import', core.lformat(LOC_FILE_NOT_EXISTS, ["py", fpath]), head='\n', ln=config.language)
|
|
300
340
|
imps = []
|
|
301
341
|
content = self.auto_read(fpath)
|
|
302
342
|
project_path = project_path or os.path.dirname(fpath)
|
|
@@ -342,6 +382,81 @@ class Compiler_Utils(Compiler_Const):
|
|
|
342
382
|
|
|
343
383
|
return imps
|
|
344
384
|
|
|
385
|
+
def find_chain_import2(self, fpath: str, search_dirs: list[str], project_path: str = None, records: dict[str, None] = None) -> list[str]:
|
|
386
|
+
r"""
|
|
387
|
+
查找文件中的所有import语句,并返回所有import的文件路径 | find all import statements in a file and return the paths of all imported files
|
|
388
|
+
PY_IMPORT_PAT: re.compile(r'\s+from\s+(.+)(?=\s+import)\s+import\s+\*')
|
|
389
|
+
:param fpath: str 目标文件路径 | target file path
|
|
390
|
+
:param search_dirs: list[str] 搜索目录 | search directories
|
|
391
|
+
:param project_path=None: str python项目中的概念,指根文件所在的目录。如果不指定,默认使用第一次调用时给定的fpath,并且稍后的递归会全部使用此路径 |
|
|
392
|
+
concept in python-project, refers to the directory where the root file is located. If not specified, the fpath given at the first call is used by default, and all subsequent recursions will use this path
|
|
393
|
+
:param records=None: dict[str, None] 记录已经查找过的文件路径,避免重复查找 | record the file paths that have been searched to avoid duplicate searches
|
|
394
|
+
"""
|
|
395
|
+
if records is None:
|
|
396
|
+
records = {}
|
|
397
|
+
if not os.path.exists(fpath):
|
|
398
|
+
core.error('Compiler.find_chain_import', core.lformat(LOC_FILE_NOT_EXISTS, [fpath]), head='\n', ln=config.language)
|
|
399
|
+
imps = []
|
|
400
|
+
content = self.auto_read(fpath)
|
|
401
|
+
project_path = project_path or os.path.dirname(fpath)
|
|
402
|
+
|
|
403
|
+
# 添加根目录和 src 目录到 search_dirs
|
|
404
|
+
root_dir = os.path.dirname(project_path) # 根目录
|
|
405
|
+
src_dir = os.path.join(root_dir, 'src') # src 目录
|
|
406
|
+
if root_dir not in search_dirs:
|
|
407
|
+
search_dirs = [root_dir] + search_dirs
|
|
408
|
+
if src_dir not in search_dirs:
|
|
409
|
+
search_dirs = [src_dir] + search_dirs
|
|
410
|
+
|
|
411
|
+
for no, line in enumerate(content.split('\n')):
|
|
412
|
+
m = self.PY_IMPORT_PAT.match(line)
|
|
413
|
+
if m:
|
|
414
|
+
target = m.group(1)
|
|
415
|
+
target_path = project_path
|
|
416
|
+
|
|
417
|
+
## 向前定位 | locate forward
|
|
418
|
+
if target.startswith('.'):
|
|
419
|
+
target_path = os.path.dirname(fpath) # 因为使用了相对路径,所以需要先定位到当前文件所在的目录 |
|
|
420
|
+
# because relative path is used, need to locate the directory where the current file is located first
|
|
421
|
+
count = 0
|
|
422
|
+
for c in target:
|
|
423
|
+
if c == '.':
|
|
424
|
+
count += 1
|
|
425
|
+
else:
|
|
426
|
+
break
|
|
427
|
+
if count > 1:
|
|
428
|
+
for _ in range(count - 1):
|
|
429
|
+
target_path = os.path.dirname(target_path)
|
|
430
|
+
|
|
431
|
+
## 向后定位 | locate backward
|
|
432
|
+
while (_idx := target.find('.')) != -1:
|
|
433
|
+
first_name = target[:_idx]
|
|
434
|
+
target_path = os.path.join(target_path, first_name)
|
|
435
|
+
target = target[_idx + 1:]
|
|
436
|
+
|
|
437
|
+
## 检查是否存在 | check if exists
|
|
438
|
+
this_path = os.path.join(target_path, target)
|
|
439
|
+
if os.path.isdir(this_path):
|
|
440
|
+
this_path = os.path.join(this_path, '__init__.py')
|
|
441
|
+
else:
|
|
442
|
+
this_path += '.py'
|
|
443
|
+
|
|
444
|
+
if not os.path.exists(this_path):
|
|
445
|
+
# 如果当前路径不存在,尝试在 search_dirs 中查找
|
|
446
|
+
for search_dir in search_dirs:
|
|
447
|
+
search_path = os.path.join(search_dir, target.replace('.', os.sep)) + ('.py' if not os.path.isdir(this_path) else os.sep + '__init__.py')
|
|
448
|
+
if os.path.exists(search_path):
|
|
449
|
+
this_path = search_path
|
|
450
|
+
break
|
|
451
|
+
else:
|
|
452
|
+
core.error('Compiler.find_chain_import', core.lformat(LOC_CHAIN_FILE_NOT_EXISTS, [fpath, no + 1, this_path]), head='\n', ln=config.language)
|
|
453
|
+
if this_path not in records:
|
|
454
|
+
records[this_path] = None
|
|
455
|
+
tmp = self.find_chain_import(this_path, search_dirs, project_path, records) + [this_path]
|
|
456
|
+
imps.extend(tmp)
|
|
457
|
+
|
|
458
|
+
return imps
|
|
459
|
+
|
|
345
460
|
@staticmethod
|
|
346
461
|
def relist_pyimports_to_jsimports(base_dir:str, pyimps:list[str]) -> list[str]:
|
|
347
462
|
"""
|
|
@@ -360,19 +475,66 @@ class Compiler_Utils(Compiler_Const):
|
|
|
360
475
|
# ---------- 自定义函数 ---------- #
|
|
361
476
|
@staticmethod
|
|
362
477
|
def stage_recursive_replace(content:str) -> str:
|
|
363
|
-
"""
|
|
478
|
+
r"""
|
|
364
479
|
替换'@recursive'为'@recursive(<fname>)', 其中<fname>为被装饰器标记的函数名 |
|
|
365
480
|
Replace '@recursive' with '@recursive(<fname>)', where <fname> is the name of the decorated function.
|
|
366
481
|
|
|
367
482
|
@\s*recursive\s+def\s+([^\s\(]+)
|
|
368
483
|
"""
|
|
369
484
|
return re.sub(r'@\s*recursive(\s+def\s+)([^\s\(]+)', r'@recursive("\2")\1\2', content)
|
|
485
|
+
|
|
486
|
+
@staticmethod
|
|
487
|
+
def process_mate_code(code):
|
|
488
|
+
# 用于存储匹配到的信息
|
|
489
|
+
mate_assignments = []
|
|
490
|
+
# 匹配变量赋值为Mate()的正则表达式,允许变量定义中包含或不包含类型注解
|
|
491
|
+
assign_pattern = re.compile(r'(\w+)\s*(?:\:\s*\w*)?\s*=\s*Mate\s*\(')
|
|
492
|
+
# 匹配类定义的正则表达式
|
|
493
|
+
class_pattern = re.compile(r'class\s+(\w+)')
|
|
494
|
+
# 用于记录当前所在的类名
|
|
495
|
+
current_class = None
|
|
496
|
+
# 将代码按行分割
|
|
497
|
+
lines = code.split('\n')
|
|
498
|
+
# 遍历每一行
|
|
499
|
+
for i, line in enumerate(lines):
|
|
500
|
+
# 匹配类定义
|
|
501
|
+
class_match = class_pattern.match(line)
|
|
502
|
+
if class_match:
|
|
503
|
+
current_class = class_match.group(1)
|
|
504
|
+
# 匹配变量赋值为Mate()
|
|
505
|
+
assign_match = assign_pattern.search(line)
|
|
506
|
+
if assign_match:
|
|
507
|
+
# 检查group(1)前面同一行内是否有#,如果有则忽略
|
|
508
|
+
comment = re.search(r'#', line[:assign_match.start()])
|
|
509
|
+
if comment:
|
|
510
|
+
continue
|
|
511
|
+
variable_name = assign_match.group(1)
|
|
512
|
+
# 存储匹配到的信息
|
|
513
|
+
mate_assignments += [(variable_name, current_class)]
|
|
514
|
+
|
|
515
|
+
output_strings = []
|
|
516
|
+
for variable_name, class_name in mate_assignments:
|
|
517
|
+
output_string = f"# > insert Object.defineProperty ({class_name}, '{variable_name}', property.call ({class_name}, {class_name}.{variable_name}._MateGet_, {class_name}.{variable_name}._MateSet_));"
|
|
518
|
+
output_strings.append(output_string)
|
|
519
|
+
|
|
520
|
+
return code + '\n'.join(output_strings)
|
|
370
521
|
|
|
371
522
|
|
|
523
|
+
@staticmethod
|
|
524
|
+
def remove_long_docstring(content:str) -> str:
|
|
525
|
+
"""
|
|
526
|
+
移除长注释 | remove long docstring
|
|
527
|
+
"""
|
|
528
|
+
code = re.sub(r'"""[^"]*"""', '', content)
|
|
529
|
+
code = re.sub(r"'''[^']*'''", '', code)
|
|
530
|
+
return code
|
|
531
|
+
|
|
372
532
|
|
|
373
533
|
class CompilerBase(Compiler_Utils):
|
|
374
534
|
|
|
375
|
-
def __init__(self
|
|
535
|
+
def __init__(self):
|
|
536
|
+
src_dir = "src"
|
|
537
|
+
build_dir = "build"
|
|
376
538
|
# check
|
|
377
539
|
if not os.path.exists(src_dir):
|
|
378
540
|
core.error('Compiler.__init__', core.lformat(LOC_FILE_NOT_EXISTS, ['src', src_dir]), head='\n', ln=config.language)
|
|
@@ -435,6 +597,7 @@ class Compiler(CompilerBase):
|
|
|
435
597
|
# 将PYFILE_PRAGMA_INSERTS.replace("\t", "").replace(" ", "")插入到文件开头
|
|
436
598
|
content = self.auto_read(fpath)
|
|
437
599
|
content = self.PYFILE_PRAGMA_INSERTS.replace("\t", "").replace(" ", "") + content
|
|
600
|
+
# content = self.remove_long_docstring(content) # 移除长注释 | remove long docstring
|
|
438
601
|
|
|
439
602
|
with open(fpath, 'w', encoding='utf-8') as f: # 注意,这里修改的是build目录下的文件,不是源文件 | Note that the file under the build directory is modified here, not the source file
|
|
440
603
|
f.write(content)
|
|
@@ -506,6 +669,13 @@ class Compiler(CompilerBase):
|
|
|
506
669
|
else:
|
|
507
670
|
_pre_sort_[fname] = 65535
|
|
508
671
|
|
|
672
|
+
# ------------------------------------ 自定义:调用process_mate_code ------------------------------------ #
|
|
673
|
+
for fpath in py_fpath:
|
|
674
|
+
content = self.auto_read(fpath)
|
|
675
|
+
content = self.process_mate_code(content) # 调用process_mate_code
|
|
676
|
+
with open(fpath, 'w', encoding='utf-8') as f:
|
|
677
|
+
f.write(content)
|
|
678
|
+
|
|
509
679
|
# ------------------------------------ DEFINE ------------------------------------ #
|
|
510
680
|
# 扫描所有# > define的内容,然后在.py中移除这些行,并记录下来
|
|
511
681
|
# | get all # > define in .py files, and record them
|
|
@@ -579,14 +749,14 @@ class Compiler(CompilerBase):
|
|
|
579
749
|
with open(fpath, 'w', encoding='utf-8') as f:
|
|
580
750
|
f.write(new_content)
|
|
581
751
|
|
|
582
|
-
# ------------------------------------
|
|
583
|
-
# 调用stage_recursive_replace
|
|
752
|
+
# ------------------------------------ 自定义:调用stage_recursive_replace ------------------------------------ #
|
|
584
753
|
for fpath in py_fpath:
|
|
585
754
|
content = self.auto_read(fpath)
|
|
586
|
-
content = self.stage_recursive_replace(content)
|
|
755
|
+
content = self.stage_recursive_replace(content) # 调用stage_recursive_replace
|
|
587
756
|
with open(fpath, 'w', encoding='utf-8') as f:
|
|
588
757
|
f.write(content)
|
|
589
758
|
|
|
759
|
+
|
|
590
760
|
core.lprint(GREEN.format('[2/6]'), LOC_DONE, " ", LOC_PREPROCESSING_FINISH, sep="", head="\r", ln=config.language)
|
|
591
761
|
return _imports, _js_imports, _pre_sort_, _pre_define_, _js_replace_
|
|
592
762
|
|
|
@@ -721,9 +891,8 @@ class Compiler(CompilerBase):
|
|
|
721
891
|
"""
|
|
722
892
|
arena_name = const.ARENA_NAMES.get(config.arena, const.ARENA_NAMES['green']) # like green -> spawn_and_swamp
|
|
723
893
|
self.TOTAL_INSERT_AT_HEAD += self.ARENA_IMPORTS_GETTER[arena_name]() # add arena imports
|
|
724
|
-
if config.arena != "blue":
|
|
725
|
-
self.TOTAL_INSERT_AT_HEAD += self.ARENA_IMPORTS_NOT_BLUE
|
|
726
894
|
total_js = f"const __VERSION__ = '{const.VERSION}';\nconst __PYTHON_VERSION__ = '{python_version_info}';" + self.TOTAL_INSERT_AT_HEAD + f"\nexport var LANGUAGE = '{config.language}';\n"
|
|
895
|
+
total_js += f"const __AUTHOR__ = '{const.AUTHOR}';\nconst __AUTHOR_CN__ = '{const.BILIBILI_NAME}';"
|
|
727
896
|
|
|
728
897
|
core.lprint(WAIT, LOC_GENERATING_TOTAL_MAIN_JS, end="", ln=config.language)
|
|
729
898
|
|
|
@@ -15,5 +15,5 @@ season = "beta"
|
|
|
15
15
|
language = 'cn'
|
|
16
16
|
# 默认路径: 用户 + ScreepsArena + beta-spawn_and_swamp + main.mjs
|
|
17
17
|
target = None
|
|
18
|
-
TARGET_GETTER = lambda: os.path.join(os.path.expanduser('~'), 'ScreepsArena', f'{season}-{const.ARENA_NAMES.get(arena, "spawn_and_swamp")}', 'main.mjs')
|
|
18
|
+
TARGET_GETTER = lambda: os.path.join(os.path.expanduser('~'), 'ScreepsArena', f'{season}-{const.ARENA_NAMES.get(arena, "spawn_and_swamp")}{"-advanced" if level in ["advance", "advanced"] else ""}', 'main.mjs')
|
|
19
19
|
|
|
@@ -9,10 +9,11 @@
|
|
|
9
9
|
#
|
|
10
10
|
import re
|
|
11
11
|
|
|
12
|
-
VERSION = "0.
|
|
13
|
-
AUTHOR = "
|
|
12
|
+
VERSION = "0.4b0"
|
|
13
|
+
AUTHOR = "●ω<🤍♪"
|
|
14
14
|
STEAM_ID = "1029562896"
|
|
15
15
|
GITHUB_NAME = "EagleBaby"
|
|
16
|
+
BILIBILI_NAME = "我阅读理解一直可以的"
|
|
16
17
|
|
|
17
18
|
ARENA_GREEN = "spawn_and_swamp"
|
|
18
19
|
ARENA_BLUE = "capture_the_flag"
|
|
Binary file
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pyscreeps-arena
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Python api|interface to play game: Screeps: Arena.
|
|
5
5
|
Author-email: 2229066748@qq.com
|
|
6
6
|
Maintainer: Eagle'sBaby
|
|
@@ -11,6 +11,14 @@ Classifier: Programming Language :: Python
|
|
|
11
11
|
Classifier: Programming Language :: Python :: 3
|
|
12
12
|
Requires-Python: >=3.10
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
|
+
Requires-Dist: pyperclip
|
|
15
|
+
Requires-Dist: colorama
|
|
16
|
+
Requires-Dist: py7zr
|
|
17
|
+
Requires-Dist: chardet
|
|
18
|
+
Requires-Dist: Transcrypt==3.9.1
|
|
19
|
+
Requires-Dist: mkdocs
|
|
20
|
+
Requires-Dist: mkdocstrings[python]
|
|
21
|
+
Requires-Dist: mkdocs-material
|
|
14
22
|
|
|
15
23
|
# PyScreeps-Arena
|
|
16
24
|
|
|
@@ -7,7 +7,7 @@ with open(r"T:\New_PC\Import_Project\uploads\pyscreeps-arena_upload\pyscreeps-ar
|
|
|
7
7
|
long_description = f.read()
|
|
8
8
|
setup(
|
|
9
9
|
name='pyscreeps-arena',
|
|
10
|
-
version='0.
|
|
10
|
+
version='0.4.0',
|
|
11
11
|
description='Python api|interface to play game: Screeps: Arena.',
|
|
12
12
|
long_description=long_description,
|
|
13
13
|
long_description_content_type='text/markdown',
|
|
@@ -26,6 +26,7 @@ setup(
|
|
|
26
26
|
entry_points={
|
|
27
27
|
'console_scripts': [
|
|
28
28
|
'pyscreeps-arena=pyscreeps_arena:CMD_NewProject',
|
|
29
|
+
'arena=pyscreeps_arena:CMD_NewProject',
|
|
29
30
|
]
|
|
30
31
|
},
|
|
31
32
|
keywords=['python', 'screeps:arena', 'screeps'],
|
|
Binary file
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyscreeps-arena-0.3.6 → pyscreeps-arena-0.4.0}/pyscreeps_arena.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|