1
+ # SPDX-FileCopyrightText: 2024 Tim Cocks for Adafruit Industries
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+ """
5
+ Karel the Robot helper class
6
+ """
7
+
1
8
import json
2
9
import time
3
10
34
41
"dark_green" ,
35
42
"turquoise" ,
36
43
"dark_blue" ,
37
- "dark_red"
44
+ "dark_red" ,
38
45
]
39
46
COLOR_VALUES = [
40
47
0xFFFFFF ,
52
59
0x008700 ,
53
60
0x00C0C0 ,
54
61
0x0000AA ,
55
- 0x800000
62
+ 0x800000 ,
56
63
]
57
64
58
65
@@ -69,10 +76,15 @@ class NoBeepersInBag(Exception):
69
76
70
77
71
78
class Karel :
72
- def __init__ (self , spritesheet_bmp , spritesheet_palette , world_width = 20 , world_height = 15 ):
73
-
74
- self .tilegrid = TileGrid (spritesheet_bmp , pixel_shader = spritesheet_palette ,
75
- default_tile = 0 , tile_width = TILE_SIZE , tile_height = TILE_SIZE )
79
+ def __init__ (self , spritesheet_bmp , spritesheet_palette ):
80
+
81
+ self .tilegrid = TileGrid (
82
+ spritesheet_bmp ,
83
+ pixel_shader = spritesheet_palette ,
84
+ default_tile = 0 ,
85
+ tile_width = TILE_SIZE ,
86
+ tile_height = TILE_SIZE ,
87
+ )
76
88
self ._direction = EAST
77
89
self .beeper_count = 0
78
90
@@ -111,15 +123,16 @@ def y(self, new_value):
111
123
112
124
class World :
113
125
def __init__ (self , display , world_width = 10 , world_height = 10 , beeper_limit = False ):
114
- print ("world init()" )
115
126
self .world_width = world_width
116
127
self .world_height = world_height
117
128
color_count = len (COLOR_NAMES )
118
129
self .background_bmp = Bitmap (world_width , world_height , color_count )
119
130
self .background_palette = Palette (color_count )
120
131
for i , color_val in enumerate (COLOR_VALUES ):
121
132
self .background_palette [i ] = color_val
122
- self .background_tilegrid = TileGrid (bitmap = self .background_bmp , pixel_shader = self .background_palette )
133
+ self .background_tilegrid = TileGrid (
134
+ bitmap = self .background_bmp , pixel_shader = self .background_palette
135
+ )
123
136
self .background_group = Group (scale = TILE_SIZE )
124
137
self .background_group .append (self .background_tilegrid )
125
138
self .display = display
@@ -128,12 +141,20 @@ def __init__(self, display, world_width=10, world_height=10, beeper_limit=False)
128
141
self .world_group .append (self .background_group )
129
142
130
143
lib_dir = "/" .join (__file__ .split ("/" )[0 :3 ])
131
- # print(lib_dir)
132
- self .spritesheet_bmp , self .spritesheet_palette = adafruit_imageload .load (f"{ lib_dir } /spritesheet_24px.png" )
144
+ self .spritesheet_bmp , self .spritesheet_palette = adafruit_imageload .load (
145
+ f"{ lib_dir } /spritesheet.png"
146
+ )
133
147
self .spritesheet_palette .make_transparent (0 )
134
148
135
- self .world_tilegrid = TileGrid (self .spritesheet_bmp , pixel_shader = self .spritesheet_palette ,
136
- tile_width = TILE_SIZE , tile_height = TILE_SIZE , width = 20 , height = 15 , default_tile = 7 )
149
+ self .world_tilegrid = TileGrid (
150
+ self .spritesheet_bmp ,
151
+ pixel_shader = self .spritesheet_palette ,
152
+ tile_width = TILE_SIZE ,
153
+ tile_height = TILE_SIZE ,
154
+ width = 20 ,
155
+ height = 15 ,
156
+ default_tile = 7 ,
157
+ )
137
158
138
159
self .beeper_limit = beeper_limit
139
160
@@ -154,24 +175,24 @@ def _init_beeper_counts(self):
154
175
155
176
self .beeper_count_labels = {}
156
177
self .beeper_counts = []
157
- for y in range (self .background_bmp . width ):
158
- self .beeper_counts .append ([0 for x in range (self .background_bmp . width )])
178
+ for _ in range (self .world_height ):
179
+ self .beeper_counts .append ([0 for x in range (self .world_width )])
159
180
160
181
def load_state (self , state_obj ):
161
182
self ._init_beeper_counts ()
162
183
if "beeper_counts" in state_obj ["input" ]:
163
184
for beeper_count_loc_str in state_obj ["input" ]["beeper_counts" ].keys ():
164
185
beeper_count_loc = [int (_ ) for _ in beeper_count_loc_str .split ("," )]
165
- print (beeper_count_loc )
166
- self .beeper_counts [world .world_height - 1 - beeper_count_loc [1 ]][beeper_count_loc [0 ]] \
167
- = state_obj ["input" ]["beeper_counts" ][beeper_count_loc_str ]
168
- for row in self .beeper_counts :
169
- print (row )
186
+ self .beeper_counts [world .world_height - 1 - beeper_count_loc [1 ]][
187
+ beeper_count_loc [0 ]
188
+ ] = state_obj ["input" ]["beeper_counts" ][beeper_count_loc_str ]
170
189
update_beeper_count_labels ()
171
190
172
191
self .karel .x = state_obj ["input" ]["karel" ]["x" ]
173
192
self .karel .y = self .world_height - 1 - state_obj ["input" ]["karel" ]["y" ]
174
- self .karel .direction = DIRECTION_WORDS .index (state_obj ["input" ]["karel" ]["direction" ])
193
+ self .karel .direction = DIRECTION_WORDS .index (
194
+ state_obj ["input" ]["karel" ]["direction" ]
195
+ )
175
196
176
197
for y , row in enumerate (state_obj ["input" ]["world" ]):
177
198
for x , cell in enumerate (row ):
@@ -185,15 +206,21 @@ def check_goal_state(self, state_obj):
185
206
if self .karel .x != state_obj ["goal" ]["karel" ]["x" ]:
186
207
print ("karel x incorrect" )
187
208
return False
188
- if self .karel .direction != DIRECTION_WORDS .index (state_obj ["goal" ]["karel" ]["direction" ]):
209
+ if self .karel .direction != DIRECTION_WORDS .index (
210
+ state_obj ["goal" ]["karel" ]["direction" ]
211
+ ):
189
212
print ("karel dir incorrect" )
190
213
return False
191
214
192
215
if "beeper_counts" in state_obj ["goal" ]:
193
216
for beeper_count_loc_str in state_obj ["goal" ]["beeper_counts" ].keys ():
194
217
beeper_count_loc = [int (_ ) for _ in beeper_count_loc_str .split ("," )]
195
- if self .beeper_counts [world .world_height - 1 - beeper_count_loc [1 ]][beeper_count_loc [0 ]] != \
196
- state_obj ["goal" ]["beeper_counts" ][beeper_count_loc_str ]:
218
+ if (
219
+ self .beeper_counts [world .world_height - 1 - beeper_count_loc [1 ]][
220
+ beeper_count_loc [0 ]
221
+ ]
222
+ != state_obj ["goal" ]["beeper_counts" ][beeper_count_loc_str ]
223
+ ):
197
224
print (f"beeper count incorrect { beeper_count_loc } " )
198
225
return False
199
226
@@ -202,34 +229,18 @@ def check_goal_state(self, state_obj):
202
229
203
230
goal_cell_index = state_obj ["goal" ]["world" ][y ][x ]
204
231
if self .world_tilegrid [x , y ] != goal_cell_index :
205
- print (f"world mismatch: { (x , y )} : { self .world_tilegrid [x , y ]} != { goal_cell_index } " )
232
+ print (
233
+ f"world mismatch: { (x , world .world_height - 1 - y )} : "
234
+ + f"{ self .world_tilegrid [x , y ]} != { goal_cell_index } "
235
+ )
206
236
return False
207
-
208
- # print(f"({x}, {y}) goal: {goal_cell_index} actual: {self.world_tilegrid[x, y]}")
209
- # if goal_cell_index == 0:
210
- # if self.karel.x != x or self.karel.y != y or self.karel.direction != EAST:
211
- # return False
212
- # elif goal_cell_index == 1:
213
- # if self.karel.x != x or self.karel.y != y or self.karel.direction != NORTH:
214
- # return False
215
- # elif goal_cell_index == 2:
216
- # if self.karel.x != x or self.karel.y != y or self.karel.direction != WEST:
217
- # return False
218
- # elif goal_cell_index == 3:
219
- # if self.karel.x != x or self.karel.y != y or self.karel.direction != SOUTH:
220
- # return False
221
- # else:
222
- # if self.world_tilegrid[x, y] != goal_cell_index:
223
- # return False
224
237
return True
225
238
226
239
227
240
world = World (board .DISPLAY )
228
241
229
242
230
243
def move ():
231
- print (f"Moving: { world .karel .direction } " )
232
-
233
244
if front_is_blocked ():
234
245
raise FrontIsBlocked ("Karel can't move there" )
235
246
@@ -313,8 +324,9 @@ def left_is_blocked():
313
324
314
325
def paint_corner (color ):
315
326
if color not in COLOR_NAMES :
316
- raise ValueError (f"Color { color } is not valid. Supported colors are { COLOR_NAMES } " )
317
- print (f"name: { color } index: { COLOR_NAMES .index (color )} " )
327
+ raise ValueError (
328
+ f"Color { color } is not valid. Supported colors are { COLOR_NAMES } "
329
+ )
318
330
world .background_bmp [world .karel .x , world .karel .y ] = COLOR_NAMES .index (color )
319
331
320
332
@@ -330,12 +342,16 @@ def update_beeper_count_labels():
330
342
if (x , y ) in world .beeper_count_labels :
331
343
world .beeper_count_labels [(x , y )].text = str (count )
332
344
else :
333
- world .beeper_count_labels [(x , y )] = Label (terminalio .FONT ,
334
- text = str (count ),
335
- color = 0x000000 ,
336
- anchor_point = (0.5 , 0.5 ),
337
- anchored_position = (x * TILE_SIZE + TILE_SIZE // 2 ,
338
- y * TILE_SIZE + TILE_SIZE // 2 ))
345
+ world .beeper_count_labels [(x , y )] = Label (
346
+ terminalio .FONT ,
347
+ text = str (count ),
348
+ color = 0x000000 ,
349
+ anchor_point = (0.5 , 0.5 ),
350
+ anchored_position = (
351
+ x * TILE_SIZE + TILE_SIZE // 2 ,
352
+ y * TILE_SIZE + TILE_SIZE // 2 ,
353
+ ),
354
+ )
339
355
world .world_group .append (world .beeper_count_labels [(x , y )])
340
356
341
357
@@ -345,8 +361,9 @@ def pick_beeper():
345
361
346
362
world .karel .beeper_count += 1
347
363
348
- world .beeper_counts [world .karel .y ][world .karel .x ] = max (0 ,
349
- world .beeper_counts [world .karel .y ][world .karel .x ] - 1 )
364
+ world .beeper_counts [world .karel .y ][world .karel .x ] = max (
365
+ 0 , world .beeper_counts [world .karel .y ][world .karel .x ] - 1
366
+ )
350
367
update_beeper_count_labels ()
351
368
if world .beeper_counts [world .karel .y ][world .karel .x ] == 0 :
352
369
world .world_tilegrid [world .karel .x , world .karel .y ] = 5
@@ -426,10 +443,11 @@ def right_is_clear():
426
443
def front_is_clear ():
427
444
return not front_is_blocked ()
428
445
446
+
429
447
def load_state_file (state_filepath ):
430
448
with open (state_filepath , "r" ) as f :
431
449
ch_obj = json .load (f )
432
450
world .load_state (ch_obj )
433
451
434
452
time .sleep (DELAY )
435
- return ch_obj
453
+ return ch_obj
0 commit comments