pyscreeps-arena 0.3.5__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.
Files changed (22) hide show
  1. {pyscreeps-arena-0.3.5 → pyscreeps-arena-0.4.0}/PKG-INFO +9 -1
  2. {pyscreeps-arena-0.3.5 → pyscreeps-arena-0.4.0}/pyscreeps_arena/__init__.py +2 -1
  3. {pyscreeps-arena-0.3.5 → pyscreeps-arena-0.4.0}/pyscreeps_arena/compiler.py +221 -27
  4. {pyscreeps-arena-0.3.5 → pyscreeps-arena-0.4.0}/pyscreeps_arena/core/config.py +1 -1
  5. {pyscreeps-arena-0.3.5 → pyscreeps-arena-0.4.0}/pyscreeps_arena/core/const.py +3 -2
  6. pyscreeps-arena-0.4.0/pyscreeps_arena/project.7z +0 -0
  7. {pyscreeps-arena-0.3.5 → pyscreeps-arena-0.4.0}/pyscreeps_arena.egg-info/PKG-INFO +9 -1
  8. {pyscreeps-arena-0.3.5 → pyscreeps-arena-0.4.0}/pyscreeps_arena.egg-info/entry_points.txt +1 -0
  9. {pyscreeps-arena-0.3.5 → pyscreeps-arena-0.4.0}/setup.py +2 -1
  10. pyscreeps-arena-0.3.5/pyscreeps_arena/project.7z +0 -0
  11. {pyscreeps-arena-0.3.5 → pyscreeps-arena-0.4.0}/pyscreeps_arena/build.py +0 -0
  12. {pyscreeps-arena-0.3.5 → pyscreeps-arena-0.4.0}/pyscreeps_arena/core/__init__.py +0 -0
  13. {pyscreeps-arena-0.3.5 → pyscreeps-arena-0.4.0}/pyscreeps_arena/core/basic.py +0 -0
  14. {pyscreeps-arena-0.3.5 → pyscreeps-arena-0.4.0}/pyscreeps_arena/core/core.py +0 -0
  15. {pyscreeps-arena-0.3.5 → pyscreeps-arena-0.4.0}/pyscreeps_arena/core/main.py +0 -0
  16. {pyscreeps-arena-0.3.5 → pyscreeps-arena-0.4.0}/pyscreeps_arena/core/utils.py +0 -0
  17. {pyscreeps-arena-0.3.5 → pyscreeps-arena-0.4.0}/pyscreeps_arena/localization.py +0 -0
  18. {pyscreeps-arena-0.3.5 → pyscreeps-arena-0.4.0}/pyscreeps_arena.egg-info/SOURCES.txt +0 -0
  19. {pyscreeps-arena-0.3.5 → pyscreeps-arena-0.4.0}/pyscreeps_arena.egg-info/dependency_links.txt +0 -0
  20. {pyscreeps-arena-0.3.5 → pyscreeps-arena-0.4.0}/pyscreeps_arena.egg-info/requires.txt +0 -0
  21. {pyscreeps-arena-0.3.5 → pyscreeps-arena-0.4.0}/pyscreeps_arena.egg-info/top_level.txt +0 -0
  22. {pyscreeps-arena-0.3.5 → 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.5
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,12 +43,12 @@ 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";
50
50
  import {Visual} from "game/visual"
51
- import {searchPath} from "game/path-finder"
51
+ import {searchPath, CostMatrix} from "game/path-finder"
52
52
  """
53
53
 
54
54
  TOTAL_INSERT_BEFORE_MAIN = """
@@ -56,22 +56,39 @@ import {searchPath} from "game/path-finder"
56
56
 
57
57
  TOTAL_APPEND_ATEND = """
58
58
  export var sch = Scheduler();
59
- var monitor = Monitor(2);
59
+ var monitor = Monitor(1);
60
60
  know.now = 0;
61
61
 
62
+ StageMachineLogicMeta.__types__ = []; // 清空js首次构造时引入的数据
62
63
  __init_my_exists_creep_before_k__();
64
+ let knowCost = 0;
65
+ let monitorCost = 0;
66
+ let stepCost = 0;
67
+ let timeLine = 0;
63
68
  export var loop = function () {
64
- know.now = get.ticks ();
65
- know.update_(know);
69
+ get.handle();
70
+ know.now = get.now;
71
+ timeLine = get.cpu_us();
72
+ know.handle();
73
+ knowCost = get.cpu_us() - timeLine;
66
74
  if (know.now === 1) {
67
75
  std.show_welcome();
68
76
  init (know);
77
+
69
78
  }
70
79
 
80
+ timeLine = get.cpu_us();
71
81
  monitor.handle();
82
+ monitorCost = get.cpu_us() - timeLine;
83
+ for (const creep of get.creeps()){
84
+ creep.handle();
85
+ }
72
86
  step (know);
87
+ timeLine = get.cpu_us();
73
88
  sch.handle();
89
+ stepCost = get.cpu_us() - timeLine;
74
90
  std.show_usage ();
91
+ print("knowCost:", knowCost, "monitorCost:", monitorCost, "stepCost:", stepCost);
75
92
  };
76
93
  """
77
94
 
@@ -109,42 +126,70 @@ export var loop = function () {
109
126
 
110
127
  ARENA_IMPORTS_GETTER = {
111
128
  const.ARENA_GREEN: lambda: f"""
112
- class BodyPart{{
129
+ class GameBodyPart{{
113
130
  constructor(){{
114
131
  }}
115
132
  }};
116
- const ScoreCollector = StructureSpawn;
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";
117
146
  """,
118
147
  const.ARENA_BLUE: lambda: f"""
119
- const ScoreCollector = StructureSpawn;
120
- import {{ Flag, BodyPart}} from 'arena/season_{config.season}/capture_the_flag/basic';
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"}';
121
158
  """,
122
159
  const.ARENA_RED: lambda: f"""
123
- class BodyPart{{
160
+ class GameBodyPart{{
124
161
  constructor(){{
125
162
  }}
126
163
  }};
127
- import {{ RESOURCE_SCORE, ScoreCollector, AreaEffect, EFFECT_DAMAGE, EFFECT_FREEZE }} from 'arena/season_{config.season}/collect_and_control/basic';
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"}';
128
169
 
129
- import ("arena/season_{config.season}/collect_and_control/basic")
130
- .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; }})
131
- .catch((error) => {{ }});
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";'}
171
+
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';"}
132
173
  """,
133
174
  const.ARENA_GRAY: lambda: f"""
134
- class BodyPart{{
175
+ class GameBodyPart{{
135
176
  constructor(){{
136
177
  }}
137
178
  }};
138
- const ScoreCollector = StructureSpawn;
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;
139
188
  import("game/prototypes")
140
- .then((module) => {{ const Flag = module.Flag; }})
141
- .catch((error) => {{ }});
189
+ .then((module) => {{ GameFlag = module.Flag; }})
190
+ .catch((error) => {{}});
142
191
  """,
143
192
  }
144
- ARENA_IMPORTS_NOT_BLUE = ""
145
- ARENA_IMPORTS_NOT_BLUE1 = """
146
- import { StructureTower } from 'game/prototypes'
147
- """
148
193
 
149
194
 
150
195
  class Compiler_Utils(Compiler_Const):
@@ -279,7 +324,7 @@ class Compiler_Utils(Compiler_Const):
279
324
  return '\n'.join(result) # 将处理后的所有代码行连接成一个字符串,并返回最终结果 | join all processed lines into a string and return
280
325
 
281
326
  def find_chain_import(self, fpath: str, search_dirs: list[str], project_path: str = None, records: dict[str, None] = None) -> list[str]:
282
- """
327
+ r"""
283
328
  查找文件中的所有import语句,并返回所有import的文件路径 | find all import statements in a file and return the paths of all imported files
284
329
  PY_IMPORT_PAT: re.compile(r'\s+from\s+(.+)(?=\s+import)\s+import\s+\*')
285
330
  :param fpath: str 目标文件路径 | target file path
@@ -291,7 +336,7 @@ class Compiler_Utils(Compiler_Const):
291
336
  if records is None:
292
337
  records = {}
293
338
  if not os.path.exists(fpath):
294
- 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)
295
340
  imps = []
296
341
  content = self.auto_read(fpath)
297
342
  project_path = project_path or os.path.dirname(fpath)
@@ -337,6 +382,81 @@ class Compiler_Utils(Compiler_Const):
337
382
 
338
383
  return imps
339
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
+
340
460
  @staticmethod
341
461
  def relist_pyimports_to_jsimports(base_dir:str, pyimps:list[str]) -> list[str]:
342
462
  """
@@ -352,10 +472,69 @@ class Compiler_Utils(Compiler_Const):
352
472
  jsimps.append('./' + '.'.join(rel_path_nodes) + '.js')
353
473
  return jsimps
354
474
 
475
+ # ---------- 自定义函数 ---------- #
476
+ @staticmethod
477
+ def stage_recursive_replace(content:str) -> str:
478
+ r"""
479
+ 替换'@recursive'为'@recursive(<fname>)', 其中<fname>为被装饰器标记的函数名 |
480
+ Replace '@recursive' with '@recursive(<fname>)', where <fname> is the name of the decorated function.
481
+
482
+ @\s*recursive\s+def\s+([^\s\(]+)
483
+ """
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)
521
+
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
+
355
532
 
356
533
  class CompilerBase(Compiler_Utils):
357
534
 
358
- def __init__(self, src_dir, build_dir):
535
+ def __init__(self):
536
+ src_dir = "src"
537
+ build_dir = "build"
359
538
  # check
360
539
  if not os.path.exists(src_dir):
361
540
  core.error('Compiler.__init__', core.lformat(LOC_FILE_NOT_EXISTS, ['src', src_dir]), head='\n', ln=config.language)
@@ -418,6 +597,7 @@ class Compiler(CompilerBase):
418
597
  # 将PYFILE_PRAGMA_INSERTS.replace("\t", "").replace(" ", "")插入到文件开头
419
598
  content = self.auto_read(fpath)
420
599
  content = self.PYFILE_PRAGMA_INSERTS.replace("\t", "").replace(" ", "") + content
600
+ # content = self.remove_long_docstring(content) # 移除长注释 | remove long docstring
421
601
 
422
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
423
603
  f.write(content)
@@ -489,6 +669,13 @@ class Compiler(CompilerBase):
489
669
  else:
490
670
  _pre_sort_[fname] = 65535
491
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
+
492
679
  # ------------------------------------ DEFINE ------------------------------------ #
493
680
  # 扫描所有# > define的内容,然后在.py中移除这些行,并记录下来
494
681
  # | get all # > define in .py files, and record them
@@ -562,6 +749,14 @@ class Compiler(CompilerBase):
562
749
  with open(fpath, 'w', encoding='utf-8') as f:
563
750
  f.write(new_content)
564
751
 
752
+ # ------------------------------------ 自定义:调用stage_recursive_replace ------------------------------------ #
753
+ for fpath in py_fpath:
754
+ content = self.auto_read(fpath)
755
+ content = self.stage_recursive_replace(content) # 调用stage_recursive_replace
756
+ with open(fpath, 'w', encoding='utf-8') as f:
757
+ f.write(content)
758
+
759
+
565
760
  core.lprint(GREEN.format('[2/6]'), LOC_DONE, " ", LOC_PREPROCESSING_FINISH, sep="", head="\r", ln=config.language)
566
761
  return _imports, _js_imports, _pre_sort_, _pre_define_, _js_replace_
567
762
 
@@ -696,9 +891,8 @@ class Compiler(CompilerBase):
696
891
  """
697
892
  arena_name = const.ARENA_NAMES.get(config.arena, const.ARENA_NAMES['green']) # like green -> spawn_and_swamp
698
893
  self.TOTAL_INSERT_AT_HEAD += self.ARENA_IMPORTS_GETTER[arena_name]() # add arena imports
699
- if config.arena != "blue":
700
- self.TOTAL_INSERT_AT_HEAD += self.ARENA_IMPORTS_NOT_BLUE
701
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}';"
702
896
 
703
897
  core.lprint(WAIT, LOC_GENERATING_TOTAL_MAIN_JS, end="", ln=config.language)
704
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.3.5"
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"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyscreeps-arena
3
- Version: 0.3.5
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
 
@@ -1,2 +1,3 @@
1
1
  [console_scripts]
2
+ arena = pyscreeps_arena:CMD_NewProject
2
3
  pyscreeps-arena = pyscreeps_arena:CMD_NewProject
@@ -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.3.5',
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'],