sonolus.py 0.1.4__py3-none-any.whl → 0.1.6__py3-none-any.whl

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.

Potentially problematic release.


This version of sonolus.py might be problematic. Click here for more details.

Files changed (79) hide show
  1. sonolus/backend/finalize.py +18 -10
  2. sonolus/backend/interpret.py +7 -7
  3. sonolus/backend/ir.py +24 -0
  4. sonolus/backend/optimize/__init__.py +0 -0
  5. sonolus/backend/{allocate.py → optimize/allocate.py} +4 -3
  6. sonolus/backend/{constant_evaluation.py → optimize/constant_evaluation.py} +7 -7
  7. sonolus/backend/{coalesce.py → optimize/copy_coalesce.py} +3 -3
  8. sonolus/backend/optimize/dead_code.py +185 -0
  9. sonolus/backend/{dominance.py → optimize/dominance.py} +2 -17
  10. sonolus/backend/{flow.py → optimize/flow.py} +6 -5
  11. sonolus/backend/{inlining.py → optimize/inlining.py} +4 -17
  12. sonolus/backend/{liveness.py → optimize/liveness.py} +69 -65
  13. sonolus/backend/optimize/optimize.py +44 -0
  14. sonolus/backend/{passes.py → optimize/passes.py} +1 -1
  15. sonolus/backend/optimize/simplify.py +191 -0
  16. sonolus/backend/{ssa.py → optimize/ssa.py} +31 -18
  17. sonolus/backend/place.py +17 -25
  18. sonolus/backend/utils.py +10 -0
  19. sonolus/backend/visitor.py +360 -101
  20. sonolus/build/cli.py +14 -3
  21. sonolus/build/compile.py +8 -8
  22. sonolus/build/engine.py +10 -5
  23. sonolus/build/project.py +30 -1
  24. sonolus/script/archetype.py +429 -138
  25. sonolus/script/array.py +25 -8
  26. sonolus/script/array_like.py +297 -0
  27. sonolus/script/bucket.py +73 -11
  28. sonolus/script/containers.py +234 -51
  29. sonolus/script/debug.py +8 -8
  30. sonolus/script/easing.py +147 -105
  31. sonolus/script/effect.py +60 -0
  32. sonolus/script/engine.py +71 -4
  33. sonolus/script/globals.py +66 -32
  34. sonolus/script/instruction.py +79 -25
  35. sonolus/script/internal/builtin_impls.py +138 -27
  36. sonolus/script/internal/constant.py +139 -0
  37. sonolus/script/internal/context.py +14 -5
  38. sonolus/script/internal/dict_impl.py +65 -0
  39. sonolus/script/internal/generic.py +6 -9
  40. sonolus/script/internal/impl.py +38 -13
  41. sonolus/script/internal/introspection.py +5 -2
  42. sonolus/script/{math.py → internal/math_impls.py} +28 -28
  43. sonolus/script/internal/native.py +3 -3
  44. sonolus/script/internal/random.py +67 -0
  45. sonolus/script/internal/range.py +81 -0
  46. sonolus/script/internal/transient.py +51 -0
  47. sonolus/script/internal/tuple_impl.py +113 -0
  48. sonolus/script/interval.py +234 -16
  49. sonolus/script/iterator.py +120 -167
  50. sonolus/script/level.py +24 -0
  51. sonolus/script/num.py +79 -47
  52. sonolus/script/options.py +78 -12
  53. sonolus/script/particle.py +37 -4
  54. sonolus/script/pointer.py +4 -4
  55. sonolus/script/print.py +22 -1
  56. sonolus/script/project.py +59 -0
  57. sonolus/script/{graphics.py → quad.py} +75 -12
  58. sonolus/script/record.py +44 -13
  59. sonolus/script/runtime.py +50 -1
  60. sonolus/script/sprite.py +198 -115
  61. sonolus/script/text.py +2 -0
  62. sonolus/script/timing.py +72 -0
  63. sonolus/script/transform.py +296 -66
  64. sonolus/script/ui.py +134 -78
  65. sonolus/script/values.py +6 -13
  66. sonolus/script/vec.py +118 -3
  67. {sonolus_py-0.1.4.dist-info → sonolus_py-0.1.6.dist-info}/METADATA +1 -1
  68. sonolus_py-0.1.6.dist-info/RECORD +89 -0
  69. sonolus/backend/dead_code.py +0 -80
  70. sonolus/backend/optimize.py +0 -37
  71. sonolus/backend/simplify.py +0 -47
  72. sonolus/script/comptime.py +0 -160
  73. sonolus/script/random.py +0 -14
  74. sonolus/script/range.py +0 -58
  75. sonolus_py-0.1.4.dist-info/RECORD +0 -84
  76. /sonolus/script/{callbacks.py → internal/callbacks.py} +0 -0
  77. {sonolus_py-0.1.4.dist-info → sonolus_py-0.1.6.dist-info}/WHEEL +0 -0
  78. {sonolus_py-0.1.4.dist-info → sonolus_py-0.1.6.dist-info}/entry_points.txt +0 -0
  79. {sonolus_py-0.1.4.dist-info → sonolus_py-0.1.6.dist-info}/licenses/LICENSE +0 -0
sonolus/script/globals.py CHANGED
@@ -8,7 +8,7 @@ from sonolus.script.internal.generic import validate_concrete_type
8
8
  from sonolus.script.internal.value import Value
9
9
 
10
10
 
11
- class GlobalInfo:
11
+ class _GlobalInfo:
12
12
  def __init__(self, name: str, size: int, blocks: dict[Mode, Block], offset: int | None):
13
13
  self.name = name
14
14
  self.size = size
@@ -16,7 +16,7 @@ class GlobalInfo:
16
16
  self.offset = offset
17
17
 
18
18
 
19
- class GlobalField(SonolusDescriptor):
19
+ class _GlobalField(SonolusDescriptor):
20
20
  def __init__(self, name: str, type_: type[Value], index: int, offset: int):
21
21
  self.name = name
22
22
  self.type = type_
@@ -49,7 +49,7 @@ class GlobalField(SonolusDescriptor):
49
49
  target._copy_from_(value)
50
50
 
51
51
 
52
- class GlobalPlaceholder:
52
+ class _GlobalPlaceholder:
53
53
  def __init__(self, type_: type[Value], blocks: dict[Mode, Block], offset: int | None):
54
54
  self.type = type_
55
55
  self.blocks = blocks
@@ -65,10 +65,10 @@ class GlobalPlaceholder:
65
65
  return self.type._from_place_(base)
66
66
 
67
67
 
68
- def create_global(cls: type, blocks: dict[Mode, Block], offset: int | None):
68
+ def _create_global(cls: type, blocks: dict[Mode, Block], offset: int | None):
69
69
  if issubclass(cls, Value):
70
70
  cls = validate_concrete_type(cls)
71
- return GlobalPlaceholder(cls, blocks, offset)
71
+ return _GlobalPlaceholder(cls, blocks, offset)
72
72
  if len(cls.__bases__) != 1:
73
73
  raise TypeError("Expected a class with no bases or a Value subclass")
74
74
  field_offset = 0
@@ -77,61 +77,61 @@ def create_global(cls: type, blocks: dict[Mode, Block], offset: int | None):
77
77
  annotation,
78
78
  ) in enumerate(inspect.get_annotations(cls, eval_str=True).items()):
79
79
  type_ = validate_concrete_type(annotation)
80
- setattr(cls, name, GlobalField(name, type_, i, field_offset))
80
+ setattr(cls, name, _GlobalField(name, type_, i, field_offset))
81
81
  field_offset += type_._size_()
82
- cls._global_info_ = GlobalInfo(cls.__name__, field_offset, blocks, offset)
82
+ cls._global_info_ = _GlobalInfo(cls.__name__, field_offset, blocks, offset)
83
83
  cls._is_comptime_value_ = True
84
84
  return cls()
85
85
 
86
86
 
87
87
  @dataclass_transform()
88
88
  def _play_runtime_environment[T](cls: type[T]) -> T:
89
- return create_global(cls, {Mode.PLAY: PlayBlock.RuntimeEnvironment}, 0)
89
+ return _create_global(cls, {Mode.PLAY: PlayBlock.RuntimeEnvironment}, 0)
90
90
 
91
91
 
92
92
  @dataclass_transform()
93
93
  def _watch_runtime_environment[T](cls: type[T]) -> T:
94
- return create_global(cls, {Mode.WATCH: WatchBlock.RuntimeEnvironment}, 0)
94
+ return _create_global(cls, {Mode.WATCH: WatchBlock.RuntimeEnvironment}, 0)
95
95
 
96
96
 
97
97
  @dataclass_transform()
98
98
  def _tutorial_runtime_environment[T](cls: type[T]) -> T:
99
- return create_global(cls, {Mode.TUTORIAL: TutorialBlock.RuntimeEnvironment}, 0)
99
+ return _create_global(cls, {Mode.TUTORIAL: TutorialBlock.RuntimeEnvironment}, 0)
100
100
 
101
101
 
102
102
  @dataclass_transform()
103
103
  def _preview_runtime_environment[T](cls: type[T]) -> T:
104
- return create_global(cls, {Mode.PREVIEW: PreviewBlock.RuntimeEnvironment}, 0)
104
+ return _create_global(cls, {Mode.PREVIEW: PreviewBlock.RuntimeEnvironment}, 0)
105
105
 
106
106
 
107
107
  @dataclass_transform()
108
108
  def _play_runtime_update[T](cls: type[T]) -> T:
109
- return create_global(cls, {Mode.PLAY: PlayBlock.RuntimeUpdate}, 0)
109
+ return _create_global(cls, {Mode.PLAY: PlayBlock.RuntimeUpdate}, 0)
110
110
 
111
111
 
112
112
  @dataclass_transform()
113
113
  def _watch_runtime_update[T](cls: type[T]) -> T:
114
- return create_global(cls, {Mode.WATCH: WatchBlock.RuntimeUpdate}, 0)
114
+ return _create_global(cls, {Mode.WATCH: WatchBlock.RuntimeUpdate}, 0)
115
115
 
116
116
 
117
117
  @dataclass_transform()
118
118
  def _preview_runtime_canvas[T](cls: type[T]) -> T:
119
- return create_global(cls, {Mode.PREVIEW: PreviewBlock.RuntimeCanvas}, 0)
119
+ return _create_global(cls, {Mode.PREVIEW: PreviewBlock.RuntimeCanvas}, 0)
120
120
 
121
121
 
122
122
  @dataclass_transform()
123
123
  def _tutorial_runtime_update[T](cls: type[T]) -> T:
124
- return create_global(cls, {Mode.TUTORIAL: TutorialBlock.RuntimeUpdate}, 0)
124
+ return _create_global(cls, {Mode.TUTORIAL: TutorialBlock.RuntimeUpdate}, 0)
125
125
 
126
126
 
127
127
  @dataclass_transform()
128
128
  def _runtime_touch_array[T](cls: type[T]) -> T:
129
- return create_global(cls, {Mode.PLAY: PlayBlock.RuntimeTouchArray}, 0)
129
+ return _create_global(cls, {Mode.PLAY: PlayBlock.RuntimeTouchArray}, 0)
130
130
 
131
131
 
132
132
  @dataclass_transform()
133
133
  def _runtime_skin_transform[T](cls: type[T]) -> T:
134
- return create_global(
134
+ return _create_global(
135
135
  cls,
136
136
  {
137
137
  Mode.PLAY: PlayBlock.RuntimeSkinTransform,
@@ -145,7 +145,7 @@ def _runtime_skin_transform[T](cls: type[T]) -> T:
145
145
 
146
146
  @dataclass_transform()
147
147
  def _runtime_particle_transform[T](cls: type[T]) -> T:
148
- return create_global(
148
+ return _create_global(
149
149
  cls,
150
150
  {
151
151
  Mode.PLAY: PlayBlock.RuntimeParticleTransform,
@@ -158,7 +158,7 @@ def _runtime_particle_transform[T](cls: type[T]) -> T:
158
158
 
159
159
  @dataclass_transform()
160
160
  def _runtime_background[T](cls: type[T]) -> T:
161
- return create_global(
161
+ return _create_global(
162
162
  cls,
163
163
  {
164
164
  Mode.PLAY: PlayBlock.RuntimeBackground,
@@ -171,52 +171,69 @@ def _runtime_background[T](cls: type[T]) -> T:
171
171
 
172
172
  @dataclass_transform()
173
173
  def _play_runtime_ui[T](cls: type[T]) -> T:
174
- return create_global(cls, {Mode.PLAY: PlayBlock.RuntimeUI}, 0)
174
+ return _create_global(cls, {Mode.PLAY: PlayBlock.RuntimeUI}, 0)
175
175
 
176
176
 
177
177
  @dataclass_transform()
178
178
  def _watch_runtime_ui[T](cls: type[T]) -> T:
179
- return create_global(cls, {Mode.WATCH: WatchBlock.RuntimeUI}, 0)
179
+ return _create_global(cls, {Mode.WATCH: WatchBlock.RuntimeUI}, 0)
180
180
 
181
181
 
182
182
  @dataclass_transform()
183
183
  def _tutorial_runtime_ui[T](cls: type[T]) -> T:
184
- return create_global(cls, {Mode.TUTORIAL: TutorialBlock.RuntimeUI}, 0)
184
+ return _create_global(cls, {Mode.TUTORIAL: TutorialBlock.RuntimeUI}, 0)
185
185
 
186
186
 
187
187
  @dataclass_transform()
188
188
  def _preview_runtime_ui[T](cls: type[T]) -> T:
189
- return create_global(cls, {Mode.PREVIEW: PreviewBlock.RuntimeUI}, 0)
189
+ return _create_global(cls, {Mode.PREVIEW: PreviewBlock.RuntimeUI}, 0)
190
190
 
191
191
 
192
192
  @dataclass_transform()
193
193
  def _play_runtime_ui_configuration[T](cls: type[T]) -> T:
194
- return create_global(cls, {Mode.PLAY: PlayBlock.RuntimeUIConfiguration}, 0)
194
+ return _create_global(cls, {Mode.PLAY: PlayBlock.RuntimeUIConfiguration}, 0)
195
195
 
196
196
 
197
197
  @dataclass_transform()
198
198
  def _watch_runtime_ui_configuration[T](cls: type[T]) -> T:
199
- return create_global(cls, {Mode.WATCH: WatchBlock.RuntimeUIConfiguration}, 0)
199
+ return _create_global(cls, {Mode.WATCH: WatchBlock.RuntimeUIConfiguration}, 0)
200
200
 
201
201
 
202
202
  @dataclass_transform()
203
203
  def _tutorial_runtime_ui_configuration[T](cls: type[T]) -> T:
204
- return create_global(cls, {Mode.TUTORIAL: TutorialBlock.RuntimeUIConfiguration}, 0)
204
+ return _create_global(cls, {Mode.TUTORIAL: TutorialBlock.RuntimeUIConfiguration}, 0)
205
205
 
206
206
 
207
207
  @dataclass_transform()
208
208
  def _preview_runtime_ui_configuration[T](cls: type[T]) -> T:
209
- return create_global(cls, {Mode.PREVIEW: PreviewBlock.RuntimeUIConfiguration}, 0)
209
+ return _create_global(cls, {Mode.PREVIEW: PreviewBlock.RuntimeUIConfiguration}, 0)
210
210
 
211
211
 
212
212
  @dataclass_transform()
213
213
  def _tutorial_instruction[T](cls: type[T]) -> T:
214
- return create_global(cls, {Mode.TUTORIAL: TutorialBlock.TutorialInstruction}, 0)
214
+ return _create_global(cls, {Mode.TUTORIAL: TutorialBlock.TutorialInstruction}, 0)
215
215
 
216
216
 
217
217
  @dataclass_transform()
218
218
  def level_memory[T](cls: type[T]) -> T:
219
- return create_global(
219
+ """Define level memory.
220
+
221
+ Level memory may be modified during gameplay in sequential callbacks (`preprocess`, `update_sequential`, `touch`).
222
+
223
+ Usage:
224
+ ```python
225
+ @level_memory
226
+ class LevelMemory:
227
+ variable: int
228
+
229
+ variable = level_data(Array[int, 10])
230
+
231
+ def f():
232
+ LevelMemory.variable = 1
233
+ variable[0] = 2
234
+ ```
235
+ """
236
+ return _create_global(
220
237
  cls,
221
238
  {
222
239
  Mode.PLAY: PlayBlock.LevelMemory,
@@ -229,7 +246,24 @@ def level_memory[T](cls: type[T]) -> T:
229
246
 
230
247
  @dataclass_transform()
231
248
  def level_data[T](cls: type[T]) -> T:
232
- return create_global(
249
+ """Define level data.
250
+
251
+ Level data may only be modified during preprocessing.
252
+
253
+ Usage:
254
+ ```python
255
+ @level_data
256
+ class LevelData:
257
+ variable: int
258
+
259
+ variable = level_data(Array[int, 10])
260
+
261
+ def f():
262
+ LevelData.variable = 1
263
+ variable[0] = 2
264
+ ```
265
+ """
266
+ return _create_global(
233
267
  cls,
234
268
  {
235
269
  Mode.PLAY: PlayBlock.LevelData,
@@ -247,12 +281,12 @@ def level_data[T](cls: type[T]) -> T:
247
281
 
248
282
  @dataclass_transform()
249
283
  def _level_score[T](cls: type[T]) -> T:
250
- return create_global(cls, {Mode.PLAY: PlayBlock.LevelScore, Mode.WATCH: WatchBlock.LevelScore}, 0)
284
+ return _create_global(cls, {Mode.PLAY: PlayBlock.LevelScore, Mode.WATCH: WatchBlock.LevelScore}, 0)
251
285
 
252
286
 
253
287
  @dataclass_transform()
254
288
  def _level_life[T](cls: type[T]) -> T:
255
- return create_global(cls, {Mode.PLAY: PlayBlock.LevelLife, Mode.WATCH: WatchBlock.LevelLife}, 0)
289
+ return _create_global(cls, {Mode.PLAY: PlayBlock.LevelLife, Mode.WATCH: WatchBlock.LevelLife}, 0)
256
290
 
257
291
 
258
292
  # engine_rom is handled by the compiler
@@ -10,36 +10,64 @@ from sonolus.script.text import StandardText
10
10
  from sonolus.script.vec import Vec2
11
11
 
12
12
 
13
- class InstructionText(Record):
13
+ class Instruction(Record):
14
+ """Tutorial instruction text.
15
+
16
+ Usage:
17
+ ```python
18
+ Instruction(id: int)
19
+ ```
20
+ """
21
+
14
22
  id: int
15
23
 
16
24
  def show(self):
25
+ """Show this instruction text."""
17
26
  show_instruction(self)
18
27
 
19
28
 
20
29
  class InstructionIcon(Record):
30
+ """Tutorial instruction icon.
31
+
32
+ Usage:
33
+ ```python
34
+ InstructionIcon(id: int)
35
+ ```
36
+ """
37
+
21
38
  id: int
22
39
 
23
40
  def paint(self, position: Vec2, size: float, rotation: float, z: float, a: float):
41
+ """Paint this instruction icon.
42
+
43
+ Args:
44
+ position: The position of the icon.
45
+ size: The size of the icon.
46
+ rotation: The rotation of the icon.
47
+ z: The z-index of the icon.
48
+ a: The alpha of the icon.
49
+ """
24
50
  _paint(self.id, position.x, position.y, size, rotation, z, a)
25
51
 
26
52
 
27
53
  @dataclass
28
- class InstructionTextInfo:
54
+ class _InstructionTextInfo:
29
55
  name: str
30
56
 
31
57
 
32
58
  @dataclass
33
- class InstructionIconInfo:
59
+ class _InstructionIconInfo:
34
60
  name: str
35
61
 
36
62
 
37
63
  def instruction(name: str) -> Any:
38
- return InstructionTextInfo(name=name)
64
+ """Define an instruction with the given name."""
65
+ return _InstructionTextInfo(name=name)
39
66
 
40
67
 
41
68
  def instruction_icon(name: str) -> Any:
42
- return InstructionIconInfo(name=name)
69
+ """Define an instruction icon with the given name."""
70
+ return _InstructionIconInfo(name=name)
43
71
 
44
72
 
45
73
  type TutorialInstructions = NewType("TutorialInstructions", Any)
@@ -48,6 +76,16 @@ type TutorialInstructionIcons = NewType("TutorialInstructionIcons", Any)
48
76
 
49
77
  @dataclass_transform()
50
78
  def instructions[T](cls: type[T]) -> T | TutorialInstructions:
79
+ """Decorator to define tutorial instructions.
80
+
81
+ Usage:
82
+ ```python
83
+ @instructions
84
+ class Instructions:
85
+ tap: StandardInstruction.TAP
86
+ other_instruction: InstructionText = instruction("Other Instruction")
87
+ ```
88
+ """
51
89
  if len(cls.__bases__) != 1:
52
90
  raise ValueError("Instructions class must not inherit from any class (except object)")
53
91
  instance = cls()
@@ -57,15 +95,15 @@ def instructions[T](cls: type[T]) -> T | TutorialInstructions:
57
95
  raise TypeError(f"Invalid annotation for instruction: {annotation}")
58
96
  annotation_type = annotation.__args__[0]
59
97
  annotation_values = annotation.__metadata__
60
- if annotation_type is not InstructionText:
98
+ if annotation_type is not Instruction:
61
99
  raise TypeError(
62
100
  f"Invalid annotation for instruction: {annotation}, expected annotation of type InstructionText"
63
101
  )
64
- if len(annotation_values) != 1 or not isinstance(annotation_values[0], InstructionTextInfo):
102
+ if len(annotation_values) != 1 or not isinstance(annotation_values[0], _InstructionTextInfo):
65
103
  raise TypeError(f"Invalid annotation for instruction: {annotation}, expected a single annotation value")
66
104
  instruction_name = annotation_values[0].name
67
105
  names.append(instruction_name)
68
- setattr(instance, name, InstructionText(i))
106
+ setattr(instance, name, Instruction(i))
69
107
  instance._instructions_ = names
70
108
  instance._is_comptime_value_ = True
71
109
  return instance
@@ -73,6 +111,16 @@ def instructions[T](cls: type[T]) -> T | TutorialInstructions:
73
111
 
74
112
  @dataclass_transform()
75
113
  def instruction_icons[T](cls: type[T]) -> T | TutorialInstructionIcons:
114
+ """Decorator to define tutorial instruction icons.
115
+
116
+ Usage:
117
+ ```python
118
+ @instruction_icons
119
+ class InstructionIcons:
120
+ hand: StandardInstructionIcon.HAND
121
+ other_icon: InstructionIcon = instruction_icon("Other Icon")
122
+ ```
123
+ """
76
124
  if len(cls.__bases__) != 1:
77
125
  raise ValueError("Instruction icons class must not inherit from any class (except object)")
78
126
  instance = cls()
@@ -86,7 +134,7 @@ def instruction_icons[T](cls: type[T]) -> T | TutorialInstructionIcons:
86
134
  raise TypeError(
87
135
  f"Invalid annotation for instruction icon: {annotation}, expected annotation of type InstructionIcon"
88
136
  )
89
- if len(annotation_values) != 1 or not isinstance(annotation_values[0], InstructionIconInfo):
137
+ if len(annotation_values) != 1 or not isinstance(annotation_values[0], _InstructionIconInfo):
90
138
  raise TypeError(
91
139
  f"Invalid annotation for instruction icon: {annotation}, expected a single annotation value"
92
140
  )
@@ -99,23 +147,27 @@ def instruction_icons[T](cls: type[T]) -> T | TutorialInstructionIcons:
99
147
 
100
148
 
101
149
  class StandardInstruction:
102
- TAP = Annotated[InstructionText, instruction(StandardText.TAP)]
103
- TAP_HOLD = Annotated[InstructionText, instruction(StandardText.TAP_HOLD)]
104
- TAP_RELEASE = Annotated[InstructionText, instruction(StandardText.TAP_RELEASE)]
105
- TAP_FLICK = Annotated[InstructionText, instruction(StandardText.TAP_FLICK)]
106
- TAP_SLIDE = Annotated[InstructionText, instruction(StandardText.TAP_SLIDE)]
107
- HOLD = Annotated[InstructionText, instruction(StandardText.HOLD)]
108
- HOLD_SLIDE = Annotated[InstructionText, instruction(StandardText.HOLD_SLIDE)]
109
- HOLD_FOLLOW = Annotated[InstructionText, instruction(StandardText.HOLD_FOLLOW)]
110
- RELEASE = Annotated[InstructionText, instruction(StandardText.RELEASE)]
111
- FLICK = Annotated[InstructionText, instruction(StandardText.FLICK)]
112
- SLIDE = Annotated[InstructionText, instruction(StandardText.SLIDE)]
113
- SLIDE_FLICK = Annotated[InstructionText, instruction(StandardText.SLIDE_FLICK)]
114
- AVOID = Annotated[InstructionText, instruction(StandardText.AVOID)]
115
- JIGGLE = Annotated[InstructionText, instruction(StandardText.JIGGLE)]
150
+ """Standard instructions."""
151
+
152
+ TAP = Annotated[Instruction, instruction(StandardText.TAP)]
153
+ TAP_HOLD = Annotated[Instruction, instruction(StandardText.TAP_HOLD)]
154
+ TAP_RELEASE = Annotated[Instruction, instruction(StandardText.TAP_RELEASE)]
155
+ TAP_FLICK = Annotated[Instruction, instruction(StandardText.TAP_FLICK)]
156
+ TAP_SLIDE = Annotated[Instruction, instruction(StandardText.TAP_SLIDE)]
157
+ HOLD = Annotated[Instruction, instruction(StandardText.HOLD)]
158
+ HOLD_SLIDE = Annotated[Instruction, instruction(StandardText.HOLD_SLIDE)]
159
+ HOLD_FOLLOW = Annotated[Instruction, instruction(StandardText.HOLD_FOLLOW)]
160
+ RELEASE = Annotated[Instruction, instruction(StandardText.RELEASE)]
161
+ FLICK = Annotated[Instruction, instruction(StandardText.FLICK)]
162
+ SLIDE = Annotated[Instruction, instruction(StandardText.SLIDE)]
163
+ SLIDE_FLICK = Annotated[Instruction, instruction(StandardText.SLIDE_FLICK)]
164
+ AVOID = Annotated[Instruction, instruction(StandardText.AVOID)]
165
+ JIGGLE = Annotated[Instruction, instruction(StandardText.JIGGLE)]
116
166
 
117
167
 
118
168
  class StandardInstructionIcon:
169
+ """Standard instruction icons."""
170
+
119
171
  HAND = Annotated[InstructionIcon, instruction_icon("#HAND")]
120
172
  ARROW = Annotated[InstructionIcon, instruction_icon("#ARROW")]
121
173
 
@@ -139,13 +191,15 @@ def _paint(
139
191
  rotation: float,
140
192
  z: float,
141
193
  a: float,
142
- ):
194
+ ) -> None:
143
195
  raise NotImplementedError()
144
196
 
145
197
 
146
- def show_instruction(inst: InstructionText, /):
198
+ def show_instruction(inst: Instruction, /):
199
+ """Show the given instruction text."""
147
200
  _TutorialInstruction.text_id = inst.id
148
201
 
149
202
 
150
203
  def clear_instruction():
204
+ """Clear the current instruction text."""
151
205
  _TutorialInstruction.text_id = -1