karel_asset.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722
  1. import operator
  2. import logging
  3. import random
  4. # Logging to console
  5. logger = logging.getLogger(__name__)
  6. logging.basicConfig(level=logging.INFO) # Set loglevel to INFO or higher to prevent console spam.
  7. """
  8. Helper functions
  9. """
  10. # Return some hex colour
  11. """
  12. Waiting for Stanford to fix a bug in the environment
  13. CIP bug: https://codeinplace.stanford.edu/cip6/report?post=ac7c4ffd-1f90-475a-b4ee-2e5b73c5348f
  14. from matplotlib import colors
  15. import decimal
  16. def get_random_colour():
  17. return decimal.Decimal(random.randrange(0,10)/10), decimal.Decimal(random.randrange(0,10)/10), decimal.Decimal(random.randrange(0,10)/10)
  18. colour = colors.rgb2hex((get_random_colour()))
  19. background = colors.rgb2hex((get_random_colour()))
  20. """
  21. def generate_random_colour():
  22. # Generate random RGB values
  23. rgb_values = [random.randrange(256), random.randrange(256), random.randrange(256)]
  24. # Convert to HEX values
  25. hex_colours = [hex(value)[2:] for value in rgb_values] # Strip the '0x' prefix
  26. # Add leading "0" for single digit values
  27. for i in range(len(hex_colours)):
  28. if len(str(hex_colours[i])) == 1:
  29. hex_colours[i] = f"0{hex_colours[i]}"
  30. # Add leading "#" to hex values
  31. colour = '#' + ''.join(hex_colours)
  32. logger.debug(f"Generated random colour: {colour}")
  33. return colour
  34. """
  35. Asset functions
  36. """
  37. # Draw a background with random colour on the canvas
  38. def generate_random_background(canvas):
  39. background = canvas.create_rectangle(
  40. 1,
  41. 1,
  42. canvas.width,
  43. canvas.height,
  44. generate_random_colour(),
  45. generate_random_colour()
  46. )
  47. return background
  48. # Erase a passed Karel from the canvas
  49. def erase_asset(asset):
  50. canvas = asset[1][0]
  51. # Erase each shape of the asset
  52. for shape in asset[0].values():
  53. canvas.delete(shape)
  54. logger.debug(f"Erased asset: {asset}")
  55. # Move a passed Karel on the canvas
  56. """
  57. Waiting for Stanford to fix a bug in the environment
  58. CIP bug: https://codeinplace.stanford.edu/cip6/report?post=7043ece9-7653-4e39-8a63-5f4544b1d74b
  59. def move_karel(canvas, karel, x, y):
  60. for shape in karel[0].values():
  61. canvas.move(shape, x, y)
  62. logger.debug(f"Moved: {karel} by {x} horizontally, {y} vertically")
  63. """
  64. # Move a passed asset relative to previous position
  65. def relative_move_asset(asset, x:int=0, y:int=0):
  66. # Update coordinates in list
  67. asset[1][1] += x
  68. asset[1][2] += y
  69. # Replace asset
  70. erase_asset(asset)
  71. new_asset = draw_karel(asset[1][0], asset[1][1], asset[1][2], asset[1][3], asset[1][4], asset[1][5], asset[1][6], asset[1][7])
  72. logger.debug(f"Moved {asset} by {x} horizontally, {y} vertically, to {new_asset}")
  73. return new_asset
  74. # Move a passed asset in relation to her orientation
  75. def orientation_move_asset(asset, direction, amount):
  76. # Direction translation
  77. # East
  78. if asset[1][4].startswith("east"):
  79. if direction.lower() == "forward" or direction.lower() == "front":
  80. asset[1][1] += amount
  81. if direction.lower() == "left":
  82. asset[1][2] -= amount
  83. if direction.lower() == "right":
  84. asset[1][2] += amount
  85. if direction.lower() == "backward" or direction.lower() == "back":
  86. asset[1][1] -= amount
  87. # North
  88. if asset[1][4].startswith("north"):
  89. if direction.lower() == "forward" or direction.lower() == "front":
  90. asset[1][2] -= amount
  91. if direction.lower() == "left":
  92. asset[1][1] -= amount
  93. if direction.lower() == "right":
  94. asset[1][1] += amount
  95. if direction.lower() == "backward" or direction.lower() == "back":
  96. asset[1][2] += amount
  97. # West
  98. if asset[1][4].startswith("west"):
  99. if direction.lower() == "forward" or direction.lower() == "front":
  100. asset[1][1] -= amount
  101. if direction.lower() == "left":
  102. asset[1][2] += amount
  103. if direction.lower() == "right":
  104. asset[1][2] -= amount
  105. if direction.lower() == "backward" or direction.lower() == "back":
  106. asset[1][1] += amount
  107. # South
  108. if asset[1][4].startswith("south"):
  109. if direction.lower() == "forward" or direction.lower() == "front":
  110. asset[1][2] += amount
  111. if direction.lower() == "left":
  112. asset[1][1] += amount
  113. if direction.lower() == "right":
  114. asset[1][1] -= amount
  115. if direction.lower() == "backward" or direction.lower() == "back":
  116. asset[1][2] -= amount
  117. # Replace asset
  118. erase_asset(asset)
  119. new_karel = draw_karel(asset[1][0], asset[1][1], asset[1][2], asset[1][3], asset[1][4], asset[1][5], asset[1][6], asset[1][7])
  120. logger.debug(f"Moved: {asset} {direction} by {amount} as {new_karel}")
  121. return new_karel
  122. # Move a passed asset to new coordinates
  123. def absolute_move_asset(asset, x, y):
  124. # Update coordinates in list
  125. asset[1][1] = x
  126. asset[1][2] = y
  127. # Replace asset
  128. erase_asset(asset)
  129. new_karel = draw_karel(asset[1][0], asset[1][1], asset[1][2], asset[1][3], asset[1][4], asset[1][5], asset[1][6], asset[1][7])
  130. logger.debug(f"Moved: {asset} by {x} horizontally, {y} vertically, to {new_karel}")
  131. return new_karel
  132. # Change the orientation of a passed asset
  133. def rotate_asset(asset, direction):
  134. # Relative turn
  135. if direction == "right" or direction == "left":
  136. # East
  137. if asset[1][4] == "east":
  138. if direction == "right":
  139. asset[1][4] = "south"
  140. if direction == "left":
  141. asset[1][4] = "north"
  142. elif asset[1][4] == "east-flipped":
  143. if direction == "right":
  144. asset[1][4] = "south-flipped"
  145. if direction == "left":
  146. asset[1][4] = "north-flipped"
  147. # North
  148. elif asset[1][4] == "north":
  149. if direction == "right":
  150. asset[1][4] = "east"
  151. if direction == "left":
  152. asset[1][4] = "west"
  153. elif asset[1][4] == "north-flipped":
  154. if direction == "right":
  155. asset[1][4] = "east-flipped"
  156. if direction == "left":
  157. asset[1][4] = "west-flipped"
  158. # West
  159. elif asset[1][4] == "west":
  160. if direction == "right":
  161. asset[1][4] = "north"
  162. if direction == "left":
  163. asset[1][4] = "south"
  164. elif asset[1][4] == "west-flipped":
  165. if direction == "right":
  166. asset[1][4] = "north-flipped"
  167. if direction == "left":
  168. asset[1][4] = "south-flipped"
  169. # South
  170. elif asset[1][4] == "south":
  171. if direction == "right":
  172. asset[1][4] = "west"
  173. if direction == "left":
  174. asset[1][4] = "east"
  175. elif asset[1][4] == "south-flipped":
  176. if direction == "right":
  177. asset[1][4] = "west-flipped"
  178. if direction == "left":
  179. asset[1][4] = "east-flipped"
  180. # Absolute rotation
  181. elif direction == "east" or direction == "east-flipped" or direction == "north" or direction == "north-flipped" or direction == "west" or direction == "west-flipped" or direction == "south" or direction == "south-flipped":
  182. asset[1][4] = direction
  183. # Syntax error
  184. else:
  185. logger.error(f"Invalid rotation direction: {direction}")
  186. # Repalce asset
  187. erase_asset(asset)
  188. new_karel = draw_karel(asset[1][0], asset[1][1], asset[1][2], asset[1][3], asset[1][4], asset[1][5], asset[1][6], asset[1][7])
  189. logger.debug(f"Rotated Karel: {asset} by {direction} as {asset[1][4]} to {new_karel}")
  190. return new_karel
  191. # Recolour a passed asset on the canvas
  192. """
  193. Waiting for Stanford to fix a bug in the environment
  194. CIP bug: https://codeinplace.stanford.edu/cip6/report?post=c36ed931-3019-4830-8ba6-655c1a513471
  195. def recolour_karel(canvas, karel, colour:str="black", background:str="white"):
  196. for name, shape in karel[0].items(): # Loop over Karel dict
  197. if name.endswith("_fill"): # Background shape
  198. canvas.set_color(shape, background)
  199. canvas.set_outline_color(shape, background)
  200. else: # Foreground shape
  201. if name.endswith("_line") or name.endswith("_corner") or name == "mouth":
  202. canvas.set_color(shape, colour)
  203. elif name == "eye":
  204. #canvas.set_color(shape, "transparent")
  205. canvas.set_outline_color(shape, colour)
  206. else: # Legs and feet
  207. canvas.set_color(shape, colour)
  208. canvas.set_outline_color(shape, colour)
  209. """
  210. def recolour_asset(asset, colour:str="black", background:str="white"):
  211. # Random colours
  212. if colour == "random":
  213. colour = generate_random_colour()
  214. if background == "random":
  215. background = generate_random_colour()
  216. # Update colours in list
  217. asset[1][5] = colour
  218. asset[1][6] = background
  219. # Replace asset
  220. erase_asset(asset)
  221. new_karel = draw_karel(asset[1][0], asset[1][1], asset[1][2], asset[1][3], asset[1][4], asset[1][5], asset[1][6], asset[1][7])
  222. logger.debug(f"Re-coloured Karel: {asset} with {colour} and {background} to {new_karel}")
  223. return new_karel
  224. # Draw a random asset on the canvas
  225. def generate_random_asset(canvas):
  226. pass
  227. """
  228. Karel functions
  229. """
  230. # Draw a random Karel outside the canvas
  231. def generate_outofbounds_random_karel(canvas, side):
  232. # Base the size on the shortest pane
  233. if canvas.width < canvas.height:
  234. size = random.randint(1, canvas.width)
  235. else:
  236. size = random.randint(1, canvas.height)
  237. # Generate random coordinates (Outside the canvas geometry)
  238. match side:
  239. case "left":
  240. centre_x = int(0 - size / 2)
  241. centre_y = random.randint(int(size / 2), int(canvas.height - size / 2))
  242. case "top":
  243. centre_x = random.randint(int(size / 2), int(canvas.height - size / 2))
  244. centre_y = int(0 - size / 2)
  245. case "right":
  246. centre_x = int(0 + size / 2)
  247. centre_y = random.randint(int(size / 2), int(canvas.height - size / 2))
  248. case "bottom":
  249. centre_x = random.randint(int(size / 2), int(canvas.height - size / 2))
  250. centre_y = int(0 + size / 2)
  251. # Generate random values
  252. orientation = random.choice(["east", "east-flipped", "north", "north-flipped", "west", "west-flipped", "south", "south-flipped"])
  253. transparent = random.choice((True, False, False))
  254. return draw_karel(canvas, centre_x, centre_y, size, orientation, "random", "random", transparent)
  255. # Draw a random Karel on the canvas
  256. def generate_random_karel(canvas):
  257. # Base the size on the shortest pane
  258. if canvas.width < canvas.height:
  259. size = random.randint(1, canvas.width)
  260. else:
  261. size = random.randint(1, canvas.height)
  262. # Generate random values (Inside the canvas geometry)
  263. centre_x = random.randint(int(size / 2), int(canvas.width - size / 2))
  264. centre_y = random.randint(int(size / 2), int(canvas.height - size / 2))
  265. orientation = random.choice(["east", "east-flipped", "north", "north-flipped", "west", "west-flipped", "south", "south-flipped"])
  266. transparent = random.choice((True, False, False, False))
  267. return draw_karel(canvas, centre_x, centre_y, size, orientation, "random", "random", transparent)
  268. # Draw a Karel
  269. def draw_karel(
  270. canvas,
  271. centre_x:int=25,
  272. centre_y:int=25,
  273. size:int=50,
  274. orientation:str="east",
  275. colour:str="black",
  276. background:str="white",
  277. transparent:bool=False
  278. ):
  279. # Body constants
  280. MARGIN = size / 8
  281. APPENDAGE_MULTIPLIER = MARGIN * 0.6
  282. # Random colours
  283. if colour == "random":
  284. colour = generate_random_colour()
  285. if background == "random":
  286. background = generate_random_colour()
  287. ''' Flipper case
  288. In order to be able to flip Karel, the operands in the forumlas must be able to switch around.
  289. Orientations are in relation to the centre of Karel.
  290. '''
  291. match orientation.lower():
  292. case "east" | "south-flipped":
  293. left_operand = operator.sub # Left / Top
  294. top_operand = operator.sub # Top / Left
  295. right_operand = operator.add # Right / Bottom
  296. bottom_operand = operator.add # Bottom / Right
  297. case "east-flipped" | "south":
  298. left_operand = operator.sub # Left / Top
  299. top_operand = operator.add # Bottom / Right
  300. right_operand = operator.add # Right / Bottom
  301. bottom_operand = operator.sub # Top / Left
  302. case "west" | "north-flipped":
  303. left_operand = operator.add # Right
  304. top_operand = operator.add # Bottom
  305. right_operand = operator.sub # Left
  306. bottom_operand = operator.sub # Top
  307. case "west-flipped" | "north":
  308. left_operand = operator.add # Right / Bottom
  309. top_operand = operator.sub # Top / Left
  310. right_operand = operator.sub # Left / Top
  311. bottom_operand = operator.add # Bottom / Right
  312. """ Coords case
  313. X and Y need to be swapped in case of a North or South facing Karel, yet the original vlaues have to be returned. (To prevent diagonal relative translation)
  314. """
  315. if orientation.lower() == "north" or orientation.lower() == "north-flipped" or orientation.lower() == "south" or orientation.lower() == "south-flipped":
  316. x = centre_y
  317. y = centre_x
  318. else:
  319. x = centre_x
  320. y = centre_y
  321. # Borders
  322. left = left_operand(x, size / 2)
  323. top = top_operand(y, size / 2)
  324. right = right_operand(x, size / 2)
  325. bottom = bottom_operand(y, size / 2)
  326. margin = size / 8
  327. appendage_multiplier = margin * 0.6
  328. # Body borders
  329. body_left = left_operand(x, size / 3)
  330. body_top = top
  331. body_right = right_operand(x, size / 3)
  332. body_bottom = bottom_operand(y, size / 2.6)
  333. eye_left = right_operand(body_left, margin)
  334. eye_top = bottom_operand(body_top, margin)
  335. eye_right = left_operand(body_right, margin)
  336. eye_bottom = top_operand(body_bottom, margin * 2)
  337. # Body coordinates
  338. top_left_corner = body_left, body_top
  339. left_diagonal_top = body_left, top_operand(body_bottom, margin)
  340. left_diagonal_bottom = eye_left, body_bottom
  341. right_diagonal_top = eye_right, body_top
  342. right_diagonal_bottom = body_right, bottom_operand(body_top, margin)
  343. bottom_right_corner = body_right, body_bottom
  344. mouth_left_corner = x, bottom_operand(eye_bottom, margin)
  345. mouth_right_corner = eye_right, mouth_left_corner[1]
  346. # Left appendage borders
  347. leftLeg_left = left_operand(body_left, margin)
  348. leftLeg_top = eye_bottom
  349. leftLeg_right = body_left
  350. leftLeg_bottom = bottom_operand(leftLeg_top, appendage_multiplier)
  351. leftFoot_left = leftLeg_left
  352. leftFoot_top = leftLeg_bottom
  353. leftFoot_right = right_operand(leftLeg_left, appendage_multiplier)
  354. leftFoot_bottom = bottom_operand(leftFoot_top, appendage_multiplier)
  355. # Right appendage borders
  356. rightLeg_left = x
  357. rightLeg_top = body_bottom
  358. rightLeg_right = right_operand(rightLeg_left, appendage_multiplier)
  359. rightLeg_bottom = bottom
  360. rightFoot_left = rightLeg_right
  361. rightFoot_top = top_operand(bottom, appendage_multiplier)
  362. rigthFoot_right = right_operand(rightLeg_right, appendage_multiplier)
  363. rightFoot_bottom = bottom
  364. # Draw Karel
  365. match orientation.lower():
  366. case "east" | "east-flipped" | "west" | "west-flipped":
  367. if not transparent:
  368. # Meat
  369. top_fill = canvas.create_rectangle(
  370. top_left_corner[0],
  371. top_left_corner[1],
  372. right_diagonal_top[0],
  373. eye_top,
  374. background,
  375. background
  376. )
  377. top_corner_fill = canvas.create_polygon(
  378. right_diagonal_top[0] , right_diagonal_top[1],
  379. right_diagonal_bottom[0], right_diagonal_bottom[1],
  380. eye_right, eye_top,
  381. color = background,
  382. outline = background
  383. )
  384. left_fill = canvas.create_rectangle(
  385. top_left_corner[0],
  386. eye_top,
  387. eye_left,
  388. left_diagonal_top[1],
  389. background,
  390. background
  391. )
  392. right_fill = canvas.create_rectangle(
  393. eye_right,
  394. eye_top,
  395. right_diagonal_bottom[0],
  396. eye_bottom,
  397. background,
  398. background
  399. )
  400. bottom_fill = canvas.create_rectangle(
  401. eye_left,
  402. eye_bottom,
  403. bottom_right_corner[0],
  404. bottom_right_corner[1],
  405. background,
  406. background
  407. )
  408. bottom_corner_fill = canvas.create_polygon(
  409. left_diagonal_top[0], left_diagonal_top[1],
  410. eye_left, left_diagonal_top[1],
  411. left_diagonal_bottom[0], left_diagonal_bottom[1],
  412. color = background,
  413. outline = background
  414. )
  415. # Outlines
  416. top_line = canvas.create_line(
  417. top_left_corner[0], top_left_corner[1],
  418. right_diagonal_top[0], right_diagonal_top[1],
  419. colour
  420. )
  421. top_corner = canvas.create_line(
  422. right_diagonal_top[0], right_diagonal_top[1],
  423. right_diagonal_bottom[0], right_diagonal_bottom[1],
  424. colour
  425. )
  426. left_line = canvas.create_line(
  427. top_left_corner[0], top_left_corner[1],
  428. left_diagonal_top[0], left_diagonal_top[1],
  429. colour
  430. )
  431. bottom_corner = canvas.create_line(
  432. left_diagonal_top[0], left_diagonal_top[1],
  433. left_diagonal_bottom[0], left_diagonal_bottom[1],
  434. colour
  435. )
  436. bottom_line = canvas.create_line(
  437. left_diagonal_bottom[0], left_diagonal_bottom[1],
  438. bottom_right_corner[0], bottom_right_corner[1],
  439. colour
  440. )
  441. right_line = canvas.create_line(
  442. right_diagonal_bottom[0], right_diagonal_bottom[1],
  443. bottom_right_corner[0], bottom_right_corner[1],
  444. colour
  445. )
  446. left_leg = canvas.create_rectangle(
  447. leftLeg_left,
  448. leftLeg_top,
  449. leftLeg_right,
  450. leftLeg_bottom,
  451. colour,
  452. colour
  453. )
  454. left_foot = canvas.create_rectangle(
  455. leftFoot_left,
  456. leftFoot_top,
  457. leftFoot_right,
  458. leftFoot_bottom,
  459. colour,
  460. colour
  461. )
  462. right_leg = canvas.create_rectangle(
  463. rightLeg_left,
  464. rightLeg_top,
  465. rightLeg_right,
  466. rightLeg_bottom,
  467. colour,
  468. colour
  469. )
  470. right_foot = canvas.create_rectangle(
  471. rightFoot_left,
  472. rightFoot_top,
  473. rigthFoot_right,
  474. rightFoot_bottom,
  475. colour,
  476. colour
  477. )
  478. eye = canvas.create_rectangle(
  479. eye_left,
  480. eye_top,
  481. eye_right,
  482. eye_bottom,
  483. "transparent",
  484. colour,
  485. )
  486. mouth = canvas.create_line(
  487. mouth_left_corner[0], mouth_left_corner[1],
  488. mouth_right_corner[0], mouth_right_corner[1],
  489. colour
  490. )
  491. case "north" | "north-flipped" | "south" | "south-flipped":
  492. if not transparent:
  493. # Meat
  494. top_fill = canvas.create_rectangle(
  495. top_left_corner[1], # Top Y
  496. right_diagonal_top[0], # Right X
  497. eye_top, # Bottom Y
  498. top_left_corner[0], # Left X
  499. background,
  500. background
  501. )
  502. top_corner_fill = canvas.create_polygon(
  503. right_diagonal_top[1] , right_diagonal_top[0],
  504. right_diagonal_bottom[1], right_diagonal_bottom[0],
  505. eye_top, eye_right,
  506. color = background,
  507. outline = background
  508. )
  509. left_fill = canvas.create_rectangle(
  510. eye_top,
  511. eye_left,
  512. left_diagonal_top[1],
  513. top_left_corner[0],
  514. background,
  515. background
  516. )
  517. right_fill = canvas.create_rectangle(
  518. eye_top,
  519. right_diagonal_bottom[0],
  520. eye_bottom,
  521. eye_right,
  522. background,
  523. background
  524. )
  525. bottom_fill = canvas.create_rectangle(
  526. eye_bottom,
  527. bottom_right_corner[0],
  528. bottom_right_corner[1],
  529. eye_left,
  530. background,
  531. background
  532. )
  533. bottom_corner_fill = canvas.create_polygon(
  534. left_diagonal_top[1], left_diagonal_top[0],
  535. left_diagonal_top[1], eye_left,
  536. left_diagonal_bottom[1], left_diagonal_bottom[0],
  537. color = background,
  538. outline = background
  539. )
  540. # Outlines
  541. top_line = canvas.create_line(
  542. top_left_corner[1], top_left_corner[0],
  543. right_diagonal_top[1], right_diagonal_top[0],
  544. colour
  545. )
  546. top_corner = canvas.create_line(
  547. right_diagonal_top[1], right_diagonal_top[0],
  548. right_diagonal_bottom[1], right_diagonal_bottom[0],
  549. colour
  550. )
  551. left_line = canvas.create_line(
  552. top_left_corner[1], top_left_corner[0],
  553. left_diagonal_top[1], left_diagonal_top[0],
  554. colour
  555. )
  556. bottom_corner = canvas.create_line(
  557. left_diagonal_top[1], left_diagonal_top[0],
  558. left_diagonal_bottom[1], left_diagonal_bottom[0],
  559. colour
  560. )
  561. bottom_line = canvas.create_line(
  562. left_diagonal_bottom[1], left_diagonal_bottom[0],
  563. bottom_right_corner[1], bottom_right_corner[0],
  564. colour
  565. )
  566. right_line = canvas.create_line(
  567. right_diagonal_bottom[1], right_diagonal_bottom[0],
  568. bottom_right_corner[1], bottom_right_corner[0],
  569. colour
  570. )
  571. left_leg = canvas.create_rectangle(
  572. leftLeg_top,
  573. leftLeg_right,
  574. leftLeg_bottom,
  575. leftLeg_left,
  576. colour,
  577. colour
  578. )
  579. left_foot = canvas.create_rectangle(
  580. leftFoot_top,
  581. leftFoot_right,
  582. leftFoot_bottom,
  583. leftFoot_left,
  584. colour,
  585. colour
  586. )
  587. right_leg = canvas.create_rectangle(
  588. rightLeg_top,
  589. rightLeg_right,
  590. rightLeg_bottom,
  591. rightLeg_left,
  592. colour,
  593. colour
  594. )
  595. right_foot = canvas.create_rectangle(
  596. rightFoot_top,
  597. rigthFoot_right,
  598. rightFoot_bottom,
  599. rightFoot_left,
  600. colour,
  601. colour
  602. )
  603. eye = canvas.create_rectangle(
  604. eye_top,
  605. eye_right,
  606. eye_bottom,
  607. eye_left,
  608. "transparent",
  609. colour,
  610. )
  611. mouth = canvas.create_line(
  612. mouth_left_corner[1], mouth_left_corner[0],
  613. mouth_right_corner[1], mouth_right_corner[0],
  614. colour
  615. )
  616. # Return each object so it can later be altered/destroyed
  617. if transparent:
  618. shapes = {
  619. "top_line": top_line,
  620. "top_corner": top_corner,
  621. "left_line": left_line,
  622. "bottom_corner": bottom_corner,
  623. "bottom_line": bottom_line,
  624. "right_line": right_line,
  625. "left_leg": left_leg,
  626. "left_foot": left_foot,
  627. "right_foot": right_foot,
  628. "right_leg": right_leg,
  629. "right_foot": right_foot,
  630. "eye": eye,
  631. "mouth": mouth
  632. }
  633. else: # Not transparent
  634. shapes = {
  635. "top_fill": top_fill,
  636. "top_corner_fill": top_corner_fill,
  637. "left_fill": left_fill,
  638. "right_fill": right_fill,
  639. "bottom_fill": bottom_fill,
  640. "bottom_corner_fill": bottom_corner_fill,
  641. "top_line": top_line,
  642. "top_corner": top_corner,
  643. "left_line": left_line,
  644. "bottom_corner": bottom_corner,
  645. "bottom_line": bottom_line,
  646. "right_line": right_line,
  647. "left_leg": left_leg,
  648. "left_foot": left_foot,
  649. "right_foot": right_foot,
  650. "right_leg": right_leg,
  651. "right_foot": right_foot,
  652. "eye": eye,
  653. "mouth": mouth
  654. }
  655. arguments = [canvas, centre_x, centre_y, size, orientation.lower(), colour, background, transparent]
  656. logger.debug(f"Created Karel: {shapes, arguments}")
  657. return [shapes, arguments]