code-battles 1.6.0 → 1.6.2
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.
|
@@ -15,6 +15,7 @@ from code_battles.utilities import (
|
|
|
15
15
|
GameCanvas,
|
|
16
16
|
console_log,
|
|
17
17
|
download_image,
|
|
18
|
+
is_worker,
|
|
18
19
|
navigate,
|
|
19
20
|
set_results,
|
|
20
21
|
show_alert,
|
|
@@ -381,7 +382,7 @@ class CodeBattles(
|
|
|
381
382
|
)
|
|
382
383
|
output += lines[string_file_indices[-1] + 1].strip() + "\n"
|
|
383
384
|
|
|
384
|
-
|
|
385
|
+
self.alert(
|
|
385
386
|
f"Code Exception in 'Player {player_index + 1}' API!",
|
|
386
387
|
output,
|
|
387
388
|
"red",
|
|
@@ -393,7 +394,7 @@ class CodeBattles(
|
|
|
393
394
|
|
|
394
395
|
self.active_players = [p for p in self.active_players if p != player_index]
|
|
395
396
|
if self.verbose:
|
|
396
|
-
|
|
397
|
+
self.alert(
|
|
397
398
|
f"{self.player_names[player_index]} was eliminated!",
|
|
398
399
|
reason,
|
|
399
400
|
"blue",
|
|
@@ -430,6 +431,33 @@ class CodeBattles(
|
|
|
430
431
|
}
|
|
431
432
|
)
|
|
432
433
|
|
|
434
|
+
def alert(
|
|
435
|
+
self,
|
|
436
|
+
title: str,
|
|
437
|
+
alert: str,
|
|
438
|
+
color: str,
|
|
439
|
+
icon: str,
|
|
440
|
+
limit_time: int = 5000,
|
|
441
|
+
is_code=True,
|
|
442
|
+
):
|
|
443
|
+
"""
|
|
444
|
+
Displays the given alert in the game UI.
|
|
445
|
+
"""
|
|
446
|
+
|
|
447
|
+
if is_worker():
|
|
448
|
+
self._alerts.append(
|
|
449
|
+
{
|
|
450
|
+
"title": title,
|
|
451
|
+
"alert": alert,
|
|
452
|
+
"color": color,
|
|
453
|
+
"icon": icon,
|
|
454
|
+
"limit_time": limit_time,
|
|
455
|
+
"is_code": is_code,
|
|
456
|
+
}
|
|
457
|
+
)
|
|
458
|
+
else:
|
|
459
|
+
show_alert(title, alert, color, icon, limit_time, is_code)
|
|
460
|
+
|
|
433
461
|
@web_only
|
|
434
462
|
def play_sound(self, sound: str, force=False):
|
|
435
463
|
"""
|
|
@@ -498,6 +526,7 @@ class CodeBattles(
|
|
|
498
526
|
if seed is None:
|
|
499
527
|
seed = Random().randint(0, 2**128)
|
|
500
528
|
self._logs = []
|
|
529
|
+
self._alerts = []
|
|
501
530
|
self._decisions = []
|
|
502
531
|
self._breakpoints = set()
|
|
503
532
|
self._decision_index = 0
|
|
@@ -540,14 +569,16 @@ class CodeBattles(
|
|
|
540
569
|
while not self.over:
|
|
541
570
|
self._should_pause = False
|
|
542
571
|
self._logs = []
|
|
572
|
+
self._alerts = []
|
|
543
573
|
decisions = self.make_decisions()
|
|
544
574
|
logs = self._logs
|
|
545
|
-
|
|
575
|
+
alerts = self._alerts
|
|
546
576
|
self.apply_decisions(decisions)
|
|
547
577
|
|
|
548
578
|
sync.update_step(
|
|
549
579
|
base64.b64encode(decisions).decode(),
|
|
550
580
|
json.dumps(logs),
|
|
581
|
+
json.dumps(alerts),
|
|
551
582
|
"true" if self.over else "false",
|
|
552
583
|
"true" if self._should_pause else "false",
|
|
553
584
|
)
|
|
@@ -640,7 +671,7 @@ class CodeBattles(
|
|
|
640
671
|
navigate(
|
|
641
672
|
f"/simulation/{simulation.map}/{'-'.join(simulation.player_names)}?seed={simulation.seed}"
|
|
642
673
|
)
|
|
643
|
-
|
|
674
|
+
self.alert(
|
|
644
675
|
"Loaded simulation file!",
|
|
645
676
|
f"{', '.join(simulation.player_names)} competed in {simulation.map} at {simulation.timestamp}",
|
|
646
677
|
"blue",
|
|
@@ -648,7 +679,7 @@ class CodeBattles(
|
|
|
648
679
|
0,
|
|
649
680
|
)
|
|
650
681
|
if simulation.game != self.__class__.__name__:
|
|
651
|
-
|
|
682
|
+
self.alert(
|
|
652
683
|
"Warning: game mismatch!",
|
|
653
684
|
f"Simulation file is for game {simulation.game} while the website is running {self.__class__.__name__}!",
|
|
654
685
|
"yellow",
|
|
@@ -656,7 +687,7 @@ class CodeBattles(
|
|
|
656
687
|
0,
|
|
657
688
|
)
|
|
658
689
|
if simulation.version != self.configure_version():
|
|
659
|
-
|
|
690
|
+
self.alert(
|
|
660
691
|
"Warning: version mismatch!",
|
|
661
692
|
f"Simulation file is for version {simulation.version} while the website is running {self.configure_version()}!",
|
|
662
693
|
"yellow",
|
|
@@ -788,13 +819,19 @@ class CodeBattles(
|
|
|
788
819
|
)
|
|
789
820
|
|
|
790
821
|
def _update_step(
|
|
791
|
-
self,
|
|
822
|
+
self,
|
|
823
|
+
decisions_str: str,
|
|
824
|
+
logs_str: str,
|
|
825
|
+
alerts_str: str,
|
|
826
|
+
is_over_str: str,
|
|
827
|
+
should_pause_str: str,
|
|
792
828
|
):
|
|
793
829
|
from js import window, document
|
|
794
830
|
|
|
795
831
|
now = time.time()
|
|
796
832
|
decisions = base64.b64decode(str(decisions_str))
|
|
797
833
|
logs: list = json.loads(str(logs_str))
|
|
834
|
+
alerts: list = json.loads(str(alerts_str))
|
|
798
835
|
is_over = str(is_over_str) == "true"
|
|
799
836
|
should_pause = str(should_pause_str) == "true"
|
|
800
837
|
|
|
@@ -802,6 +839,7 @@ class CodeBattles(
|
|
|
802
839
|
self._breakpoints.add(len(self._decisions))
|
|
803
840
|
self._decisions.append(decisions)
|
|
804
841
|
self._logs.append(logs)
|
|
842
|
+
self._alerts.append(alerts)
|
|
805
843
|
|
|
806
844
|
if is_over:
|
|
807
845
|
try:
|
|
@@ -839,7 +877,7 @@ class CodeBattles(
|
|
|
839
877
|
for index, api_code in enumerate(player_codes):
|
|
840
878
|
if api_code != "" and api_code is not None:
|
|
841
879
|
if f"class MyBot({bot_base_class_name}):" not in api_code:
|
|
842
|
-
|
|
880
|
+
self.alert(
|
|
843
881
|
f"Code Exception in 'Player {index + 1}' API!",
|
|
844
882
|
f"Missing line:\nclass MyBot({bot_base_class_name}):",
|
|
845
883
|
"red",
|
|
@@ -875,7 +913,7 @@ class CodeBattles(
|
|
|
875
913
|
)
|
|
876
914
|
output += lines[string_file_indices[-1] + 1].strip() + "\n"
|
|
877
915
|
|
|
878
|
-
|
|
916
|
+
self.alert(
|
|
879
917
|
f"Code Exception in 'Player {index + 1}' API!",
|
|
880
918
|
output,
|
|
881
919
|
"red",
|
|
@@ -922,6 +960,9 @@ class CodeBattles(
|
|
|
922
960
|
log["text"],
|
|
923
961
|
log["color"],
|
|
924
962
|
)
|
|
963
|
+
alerts = self._alerts[self._decision_index]
|
|
964
|
+
for alert in alerts:
|
|
965
|
+
self.alert(**alert)
|
|
925
966
|
self.apply_decisions(self._decisions[self._decision_index])
|
|
926
967
|
self._decision_index += 1
|
|
927
968
|
|
|
@@ -239,6 +239,33 @@ class GameCanvas:
|
|
|
239
239
|
self.context.lineTo(end_x, end_y)
|
|
240
240
|
self.context.stroke()
|
|
241
241
|
|
|
242
|
+
def draw_rectangle(
|
|
243
|
+
self,
|
|
244
|
+
start_x: int,
|
|
245
|
+
start_y: int,
|
|
246
|
+
width: int,
|
|
247
|
+
height: int,
|
|
248
|
+
fill="black",
|
|
249
|
+
stroke="transparent",
|
|
250
|
+
stroke_width=2,
|
|
251
|
+
board_index=0,
|
|
252
|
+
):
|
|
253
|
+
"""
|
|
254
|
+
Draws the given rectangle with the top-left corner at `(start_x, start_y)` (in map pixels) and with the specified `width` and `height` (in map pixels) with the given stroke and fill.
|
|
255
|
+
"""
|
|
256
|
+
|
|
257
|
+
start_x, start_y = self._translate_position(board_index, start_x, start_y)
|
|
258
|
+
width *= self._scale
|
|
259
|
+
height *= self._scale
|
|
260
|
+
|
|
261
|
+
self.context.fillStyle = fill
|
|
262
|
+
self.context.strokeStyle = stroke
|
|
263
|
+
self.context.lineWidth = stroke_width * self._scale
|
|
264
|
+
self.context.beginPath()
|
|
265
|
+
self.context.rect(start_x, start_y, width, height)
|
|
266
|
+
self.context.stroke()
|
|
267
|
+
self.context.fill()
|
|
268
|
+
|
|
242
269
|
def draw_circle(
|
|
243
270
|
self,
|
|
244
271
|
x: int,
|
package/package.json
CHANGED