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)
<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>
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:
| 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().
| 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 |
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.
| 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 |
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)
When Kara cannot execute a command, a KaraException is raised:
Tree blocking the path! — kara.move() would walk into a tree or boundaryCannot push mushroom — blocked! — the cell behind the mushroom is occupiedAlready a leaf here! — kara.putLeaf() on a cell that already has a leafNo leaf here! — kara.removeLeaf() on an empty cellThe exception message is shown in the console panel below the world.
<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.
<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>
| Element | Description |
|---|---|
<kara-world> | Grid world definition (same format as in <kara-editor>) |
| Text nodes | Starter 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). |
| Attribute | Default | Description |
|---|---|---|
id | — | Enables localStorage persistence of the student's code and exercise status |
step | 200 | Animation delay in milliseconds |
timeout | 30 | Maximum run time in seconds |
hidesolution | off | Hides the "Show solution" button (remove the attribute to release the solution to students) |
Test assertions are plain Python code. The following names are available in scope:
| Name | Type | Description |
|---|---|---|
kara.x | int | Kara's current column (0-indexed from the left) |
kara.y | int | Kara's current row (0-indexed from the top) |
kara.direction | str | 'right', 'down', 'left', or 'up' |
kara.onLeaf() | bool | True if Kara is standing on a leaf |
kara.treeFront() | bool | True if there is a tree directly ahead |
kara.mushroomFront() | bool | True if there is a mushroom directly ahead |
world_leaf_at(x, y) | bool | True if there is a leaf at column x, row y |
world_mushroom_at(x, y) | bool | True if there is a mushroom at column x, row y |
world_leaves() | int | Number 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.
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>
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>
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:
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):