Kara — Grid World Guide

Kara is a ladybug that lives in a grid world. She can move, turn, pick up and place leaves, and push mushrooms. Trees block her path.

The <kara-editor> component is a variant of <bottom-editor> (Documentation →)tailored for Kara programs: no imports needed, animated step-by-step execution, and a compact console showing only error messages.

Source: github.com/tkilla77/python_editor_wasm · Original Kara (SwissEduc)


Quick start

<script type="module" src="https://bottom.ch/editor/stable/kara-editor.js"></script>

<kara-editor>
<kara-world>
#########
#...>...#
#########
</kara-world>
kara.move()
kara.move()
kara.turnLeft()
</kara-editor>
######### #...>...# ######### kara.move() kara.move() kara.turnLeft()

The world

Define the world inside a <kara-world> child element using a simple text grid:

Character Meaning
# Tree (also used for borders)
T Tree (inside the grid)
> Kara facing right
b Kara facing left (use b in HTML — < is also accepted but breaks HTML parsing)
^ Kara facing up
v Kara facing down
e / s / w / n Kara on a leaf, facing right / down / left / up (compass mnemonic)
L Leaf
M Mushroom
. Empty cell

If no <kara-world> is given, a default empty grid is used.

Lowercase compass chars (e/s/w/n) let Kara start on a leaf — useful when the goal is to leave the leaf behind or pick it up immediately:

######### #..e....# ######### kara.removeLeaf() kara.move() kara.move() kara.putLeaf()

Commands

Command Description
kara.move() Move one step in the current direction
kara.turnLeft() Turn 90° counter-clockwise
kara.turnRight() Turn 90° clockwise
kara.putLeaf() Place a leaf on the current cell
kara.removeLeaf() Pick up the leaf on the current cell

await is inserted automatically — just write kara.move(), not await kara.move().


Sensors

Sensor Returns
kara.treeFront() True if there is a tree directly ahead
kara.treeLeft() True if there is a tree to the left
kara.treeRight() True if there is a tree to the right
kara.mushroomFront() True if there is a mushroom directly ahead
kara.onLeaf() True if Kara is standing on a leaf

Mushrooms

Kara can push a mushroom if the cell behind it is empty or has a leaf. Pushing into a tree or another mushroom raises a KaraException.

########## #..>M....# ########## kara.move() kara.move() kara.move()

Sensors example

########## #>.L.L.LT# #........# ########## while not kara.treeFront(): kara.move() if kara.onLeaf(): kara.removeLeaf() else: kara.putLeaf()

Attributes

Attribute Default Description
step 200 Animation delay between steps in milliseconds; 0 for instant
autorun off Run the program automatically when Pyodide is ready
timeout 30 Maximum run time in seconds; inf to disable

Labyrinth Example

TTTTTTTTTTTTTTTTTT T> T TTTTTTTTTTTTTTTT T T T T TTT TTTTTTTTTTTT T T T TTTTTTTT TTTTTTTTT T T T TTT TTTTTTTTTTTT T T T TTTTTTTT TTTTTTTTT T T T TTT TTTTTTTTTTTT T T T TTTTTTTT TTTTTTTTT T T TTTTTTTTTTTTLTTTTT while not kara.onLeaf(): if not kara.treeRight(): kara.turnRight() kara.move() elif not kara.treeFront(): kara.move() else: kara.turnLeft()

User-defined functions

Regular Python def functions work as expected — the editor automatically makes them async and inserts await before Kara commands, so you never need to write those yourself.

def go_and_return(steps):
    for i in range(steps):
        kara.move()
    kara.turnLeft()
    kara.turnLeft()
    for i in range(steps):
        kara.move()
    kara.turnLeft()
    kara.turnLeft()

go_and_return(3)

Exceptions

When Kara cannot execute a command, a KaraException is raised:

The exception message is shown in the console panel below the world.


Exercises (<kara-exercise>)

<kara-exercise> extends <kara-editor> with exercise semantics: an optional reference solution and optional automated test assertions that check the final world state after the student's code runs.

Quick start

<script type="module" src="https://bottom.ch/editor/stable/kara-exercise.js"></script>

<kara-exercise id="ex-walk">
  <kara-world>
  #######
  #>...L#
  #######
  </kara-world>

  <!-- starter code: plain text nodes -->

  <kara-solution>
  while not kara.treeFront():
      kara.move()
  </kara-solution>

  <kara-tests>
  assert kara.x == 5, f"Expected x=5, got {kara.x}"
  assert kara.onLeaf(), "Kara should be standing on the leaf"
  </kara-tests>
</kara-exercise>
####### #>...L# ####### while not kara.treeFront(): kara.move() assert kara.x == 5, f"Expected x=5, got {kara.x}" assert kara.y == 1 assert kara.direction == 'right' assert kara.onLeaf(), "Kara should be standing on the leaf"

Child elements

ElementDescription
<kara-world>Grid world definition (same format as in <kara-editor>)
Text nodesStarter code shown in the editor
<kara-solution>Reference solution revealed when the student clicks "Show solution"
<kara-tests>Python assertions run after the student's code; kara and world helpers are in scope. May contain a <kara-world> child to specify an expected final world state (see below).

Attributes

AttributeDefaultDescription
idEnables localStorage persistence of the student's code and exercise status
step200Animation delay in milliseconds
timeout30Maximum run time in seconds
hidesolutionoffHides the "Show solution" button (remove the attribute to release the solution to students)

Test API

Test assertions are plain Python code. The following names are available in scope:

NameTypeDescription
kara.xintKara's current column (0-indexed from the left)
kara.yintKara's current row (0-indexed from the top)
kara.directionstr'right', 'down', 'left', or 'up'
kara.onLeaf()boolTrue if Kara is standing on a leaf
kara.treeFront()boolTrue if there is a tree directly ahead
kara.mushroomFront()boolTrue if there is a mushroom directly ahead
world_leaf_at(x, y)boolTrue if there is a leaf at column x, row y
world_mushroom_at(x, y)boolTrue if there is a mushroom at column x, row y
world_leaves()intNumber of leaves currently in the world (useful for "remove all" or "plant exactly N" tasks)

All commands and sensors from the commands and sensors tables above are also available in test assertions — useful for checking final sensor state after the program ends.

Exercise with world-state tests

This exercise checks that Kara placed a leaf on a specific cell:

<kara-exercise id="ex-leaf">
  <kara-world>
  ########
  #>.....#
  ########
  </kara-world>
  <kara-solution>
  kara.move()
  kara.move()
  kara.move()
  kara.putLeaf()
  </kara-solution>
  <kara-tests>
  assert world_leaf_at(4, 1), f"Expected a leaf at (4,1)"
  assert kara.x == 4
  </kara-tests>
</kara-exercise>
######## #>.....# ######## kara.move() kara.move() kara.move() kara.putLeaf() assert world_leaf_at(4, 1), f"Expected a leaf at (4,1)" assert kara.x == 4, f"Expected kara at x=4, got {kara.x}"

Counting leaves with world_leaves()

Useful for "remove all leaves" or "plant exactly N leaves" tasks:

<kara-tests>
assert world_leaves() == 0, f"All leaves should be gone, {world_leaves()} remain"
</kara-tests>
########## #>L.L.L.T# ########## while not kara.treeFront(): kara.move() if kara.onLeaf(): kara.removeLeaf() assert world_leaves() == 0, f"All leaves should be removed, {world_leaves()} remain"

Target-world assertions

Place a <kara-world> inside <kara-tests> to describe the expected final world state. Every cell is compared (leaf / mushroom / tree / empty). If the expected world includes a Kara direction character, her final position and direction are also checked; omit Kara from the target world to skip that check.

<kara-tests>
  <kara-world>
  #######
  #....>#
  #######
  </kara-world>
</kara-tests>

Plain assertions can follow the <kara-world> element and run after the world check. On failure the error lists each mismatched cell and, if applicable, Kara's expected vs. actual position and direction.

The next exercise asks the student to move Kara to the right wall — the target world includes Kara's final position and direction:

####### #>....# ####### while not kara.treeFront(): kara.move() ####### #....># #######

This variant checks only that all leaves were consumed (no Kara char in target → position not checked), and uses a starting world where Kara already stands on the first leaf (e = facing right, on a leaf):

######## #eL.L..# ######## while not kara.treeFront(): if kara.onLeaf(): kara.removeLeaf() kara.move() ######## #......# ########