From 89f56289acc7877f9ca748c51d4fef3313ba8853 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Mon, 16 Dec 2024 20:58:52 -0600 Subject: [PATCH 1/3] karel initial commit --- .../chapters/karel_ch01.json | 38 ++ .../chapters/karel_ch02.json | 38 ++ .../chapters/karel_ch03a.json | 38 ++ .../chapters/karel_ch03b.json | 38 ++ .../chapters/karel_ch04.json | 38 ++ .../chapters/karel_ch05a.json | 41 ++ .../chapters/karel_ch05b.json | 39 ++ .../chapters/karel_ch05c.json | 44 ++ .../chapters/karel_ch06a.json | 38 ++ .../chapters/karel_ch06b.json | 38 ++ .../chapters/karel_ch07.json | 38 ++ .../chapters/karel_ch08.json | 41 ++ .../chapters/karel_ch_template.json | 38 ++ CircuitPython_Karel_The_Robot/code.py | 5 + .../karel/__init__.py | 0 .../karel/circuitpythonkarel.py | 435 ++++++++++++++++++ .../karel/spritesheet.png | Bin 0 -> 4803 bytes 17 files changed, 947 insertions(+) create mode 100644 CircuitPython_Karel_The_Robot/chapters/karel_ch01.json create mode 100644 CircuitPython_Karel_The_Robot/chapters/karel_ch02.json create mode 100644 CircuitPython_Karel_The_Robot/chapters/karel_ch03a.json create mode 100644 CircuitPython_Karel_The_Robot/chapters/karel_ch03b.json create mode 100644 CircuitPython_Karel_The_Robot/chapters/karel_ch04.json create mode 100644 CircuitPython_Karel_The_Robot/chapters/karel_ch05a.json create mode 100644 CircuitPython_Karel_The_Robot/chapters/karel_ch05b.json create mode 100644 CircuitPython_Karel_The_Robot/chapters/karel_ch05c.json create mode 100644 CircuitPython_Karel_The_Robot/chapters/karel_ch06a.json create mode 100644 CircuitPython_Karel_The_Robot/chapters/karel_ch06b.json create mode 100644 CircuitPython_Karel_The_Robot/chapters/karel_ch07.json create mode 100644 CircuitPython_Karel_The_Robot/chapters/karel_ch08.json create mode 100644 CircuitPython_Karel_The_Robot/chapters/karel_ch_template.json create mode 100644 CircuitPython_Karel_The_Robot/code.py create mode 100644 CircuitPython_Karel_The_Robot/karel/__init__.py create mode 100644 CircuitPython_Karel_The_Robot/karel/circuitpythonkarel.py create mode 100644 CircuitPython_Karel_The_Robot/karel/spritesheet.png diff --git a/CircuitPython_Karel_The_Robot/chapters/karel_ch01.json b/CircuitPython_Karel_The_Robot/chapters/karel_ch01.json new file mode 100644 index 000000000..ca435b4ed --- /dev/null +++ b/CircuitPython_Karel_The_Robot/chapters/karel_ch01.json @@ -0,0 +1,38 @@ +{ + "input": { + "karel": { + "x": 0, + "y": 0, + "direction": "east" + }, + "world": [ + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 7, 7, 7, 7, 7, 7, 7], + [6, 6, 5, 7, 7, 7, 7, 7, 7, 7], + [5, 4, 5, 7, 7, 7, 7, 7, 7, 7] + ]}, + "goal": { + "karel": { + "x": 0, + "y": 2, + "direction": "west" + }, + "world": [ + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [4, 5, 5, 7, 7, 7, 7, 7, 7, 7], + [6, 6, 5, 7, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 7, 7, 7, 7, 7, 7, 7] + ]} +} \ No newline at end of file diff --git a/CircuitPython_Karel_The_Robot/chapters/karel_ch02.json b/CircuitPython_Karel_The_Robot/chapters/karel_ch02.json new file mode 100644 index 000000000..432acd714 --- /dev/null +++ b/CircuitPython_Karel_The_Robot/chapters/karel_ch02.json @@ -0,0 +1,38 @@ +{ + "input": { + "karel": { + "x": 0, + "y": 0, + "direction": "east" + }, + "world": [ + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 7, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 7, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 7, 7, 7, 7], + [5, 4, 5, 6, 6, 6, 7, 7, 7, 7] + ]}, + "goal": { + "karel": { + "x": 5, + "y": 1, + "direction": "east" + }, + "world": [ + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 7, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 7, 7, 7, 7], + [5, 5, 5, 5, 4, 5, 7, 7, 7, 7], + [5, 5, 5, 6, 6, 6, 7, 7, 7, 7] + ]} +} \ No newline at end of file diff --git a/CircuitPython_Karel_The_Robot/chapters/karel_ch03a.json b/CircuitPython_Karel_The_Robot/chapters/karel_ch03a.json new file mode 100644 index 000000000..432acd714 --- /dev/null +++ b/CircuitPython_Karel_The_Robot/chapters/karel_ch03a.json @@ -0,0 +1,38 @@ +{ + "input": { + "karel": { + "x": 0, + "y": 0, + "direction": "east" + }, + "world": [ + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 7, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 7, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 7, 7, 7, 7], + [5, 4, 5, 6, 6, 6, 7, 7, 7, 7] + ]}, + "goal": { + "karel": { + "x": 5, + "y": 1, + "direction": "east" + }, + "world": [ + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 7, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 7, 7, 7, 7], + [5, 5, 5, 5, 4, 5, 7, 7, 7, 7], + [5, 5, 5, 6, 6, 6, 7, 7, 7, 7] + ]} +} \ No newline at end of file diff --git a/CircuitPython_Karel_The_Robot/chapters/karel_ch03b.json b/CircuitPython_Karel_The_Robot/chapters/karel_ch03b.json new file mode 100644 index 000000000..e907d61c3 --- /dev/null +++ b/CircuitPython_Karel_The_Robot/chapters/karel_ch03b.json @@ -0,0 +1,38 @@ +{ + "input": { + "karel": { + "x": 0, + "y": 9, + "direction": "east" + }, + "world": [ + [5, 5, 5, 5, 6, 6, 5, 5, 5, 5], + [5, 5, 5, 5, 6, 6, 5, 5, 4, 5], + [5, 5, 5, 5, 6, 6, 5, 5, 5, 5], + [5, 5, 5, 5, 6, 6, 5, 5, 5, 5], + [5, 5, 5, 5, 5, 5, 5, 5, 5, 5], + [5, 5, 5, 5, 5, 5, 5, 5, 5, 5], + [5, 5, 5, 5, 5, 5, 5, 5, 5, 5], + [5, 5, 5, 5, 5, 5, 5, 5, 5, 5], + [5, 5, 5, 5, 5, 5, 5, 5, 5, 5], + [5, 5, 5, 5, 5, 5, 5, 5, 5, 5] + ]}, + "goal": { + "karel": { + "x": 1, + "y": 1, + "direction": "west" + }, + "world": [ + [5, 5, 5, 5, 6, 6, 5, 5, 5, 5], + [5, 5, 5, 5, 6, 6, 5, 5, 5, 5], + [5, 5, 5, 5, 6, 6, 5, 5, 5, 5], + [5, 5, 5, 5, 6, 6, 5, 5, 5, 5], + [5, 5, 5, 5, 5, 5, 5, 5, 5, 5], + [5, 5, 5, 5, 5, 5, 5, 5, 5, 5], + [5, 5, 5, 5, 5, 5, 5, 5, 5, 5], + [5, 5, 5, 5, 5, 5, 5, 5, 5, 5], + [5, 4, 5, 5, 5, 5, 5, 5, 5, 5], + [5, 5, 5, 5, 5, 5, 5, 5, 5, 5] + ]} +} \ No newline at end of file diff --git a/CircuitPython_Karel_The_Robot/chapters/karel_ch04.json b/CircuitPython_Karel_The_Robot/chapters/karel_ch04.json new file mode 100644 index 000000000..a4e369d9d --- /dev/null +++ b/CircuitPython_Karel_The_Robot/chapters/karel_ch04.json @@ -0,0 +1,38 @@ +{ + "input": { + "karel": { + "x": 0, + "y": 1, + "direction": "east" + }, + "world": [ + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 5, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 5, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 5, 7, 7, 7, 7, 7], + [6, 5, 6, 6, 6, 7, 7, 7, 7, 7] + ]}, + "goal": { + "karel": { + "x": 2, + "y": 1, + "direction": "east" + }, + "world": [ + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 5, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 5, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 5, 7, 7, 7, 7, 7], + [6, 4, 6, 6, 6, 7, 7, 7, 7, 7] + ]} +} \ No newline at end of file diff --git a/CircuitPython_Karel_The_Robot/chapters/karel_ch05a.json b/CircuitPython_Karel_The_Robot/chapters/karel_ch05a.json new file mode 100644 index 000000000..f92b163ac --- /dev/null +++ b/CircuitPython_Karel_The_Robot/chapters/karel_ch05a.json @@ -0,0 +1,41 @@ +{ + "input": { + "karel": { + "x": 0, + "y": 0, + "direction": "east" + }, + "world": [ + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 7, 7, 7, 7, 7, 7] + ]}, + "goal": { + "karel": { + "x": 2, + "y": 0, + "direction": "east" + }, + "beeper_counts": { + "1, 0": 42 + }, + "world": [ + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 7, 7, 7, 7, 7, 7], + [5, 4, 5, 5, 7, 7, 7, 7, 7, 7] + ]} +} \ No newline at end of file diff --git a/CircuitPython_Karel_The_Robot/chapters/karel_ch05b.json b/CircuitPython_Karel_The_Robot/chapters/karel_ch05b.json new file mode 100644 index 000000000..aa8b02d2f --- /dev/null +++ b/CircuitPython_Karel_The_Robot/chapters/karel_ch05b.json @@ -0,0 +1,39 @@ +{ + "input": { + "karel": { + "x": 0, + "y": 0, + "direction": "east" + }, + "world": [ + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 7, 7, 7, 7, 7, 7] + ]}, + "goal": { + "karel": { + "x": 0, + "y": 0, + "direction": "east" + }, + + "world": [ + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [4, 5, 5, 4, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 7, 7, 7, 7, 7, 7], + [4, 5, 5, 4, 7, 7, 7, 7, 7, 7] + ]} +} \ No newline at end of file diff --git a/CircuitPython_Karel_The_Robot/chapters/karel_ch05c.json b/CircuitPython_Karel_The_Robot/chapters/karel_ch05c.json new file mode 100644 index 000000000..deca9dbd3 --- /dev/null +++ b/CircuitPython_Karel_The_Robot/chapters/karel_ch05c.json @@ -0,0 +1,44 @@ +{ + "input": { + "karel": { + "x": 0, + "y": 0, + "direction": "east" + }, + "world": [ + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 7, 7, 7, 7, 7, 7] + ]}, + "goal": { + "karel": { + "x": 0, + "y": 0, + "direction": "east" + }, + "beeper_counts": { + "0, 0": 5, + "3, 0": 5, + "0, 3": 5, + "3, 3": 5 + }, + "world": [ + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [4, 5, 5, 4, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 7, 7, 7, 7, 7, 7], + [4, 5, 5, 4, 7, 7, 7, 7, 7, 7] + ]} +} \ No newline at end of file diff --git a/CircuitPython_Karel_The_Robot/chapters/karel_ch06a.json b/CircuitPython_Karel_The_Robot/chapters/karel_ch06a.json new file mode 100644 index 000000000..877b03831 --- /dev/null +++ b/CircuitPython_Karel_The_Robot/chapters/karel_ch06a.json @@ -0,0 +1,38 @@ +{ + "input": { + "karel": { + "x": 0, + "y": 0, + "direction": "east" + }, + "world": [ + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 7, 7, 7] + ]}, + "goal": { + "karel": { + "x": 6, + "y": 0, + "direction": "east" + }, + "world": [ + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 7, 7, 7] + ]} +} \ No newline at end of file diff --git a/CircuitPython_Karel_The_Robot/chapters/karel_ch06b.json b/CircuitPython_Karel_The_Robot/chapters/karel_ch06b.json new file mode 100644 index 000000000..93f73d7e3 --- /dev/null +++ b/CircuitPython_Karel_The_Robot/chapters/karel_ch06b.json @@ -0,0 +1,38 @@ +{ + "input": { + "karel": { + "x": 0, + "y": 0, + "direction": "east" + }, + "world": [ + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 7, 7, 7] + ]}, + "goal": { + "karel": { + "x": 6, + "y": 0, + "direction": "east" + }, + "world": [ + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 7, 7, 7], + [4, 4, 4, 4, 4, 4, 4, 7, 7, 7] + ]} +} \ No newline at end of file diff --git a/CircuitPython_Karel_The_Robot/chapters/karel_ch07.json b/CircuitPython_Karel_The_Robot/chapters/karel_ch07.json new file mode 100644 index 000000000..3246aab90 --- /dev/null +++ b/CircuitPython_Karel_The_Robot/chapters/karel_ch07.json @@ -0,0 +1,38 @@ +{ + "input": { + "karel": { + "x": 0, + "y": 0, + "direction": "east" + }, + "world": [ + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 5, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 5, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 5, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 5, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 5, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 5, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 5, 7, 7], + [5, 4, 5, 4, 4, 5, 4, 5, 7, 7] + ]}, + "goal": { + "karel": { + "x": 7, + "y": 0, + "direction": "east" + }, + "world": [ + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 5, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 5, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 5, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 5, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 5, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 5, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 5, 7, 7], + [4, 5, 4, 5, 5, 4, 5, 4, 7, 7] + ]} +} \ No newline at end of file diff --git a/CircuitPython_Karel_The_Robot/chapters/karel_ch08.json b/CircuitPython_Karel_The_Robot/chapters/karel_ch08.json new file mode 100644 index 000000000..66f2ccd5f --- /dev/null +++ b/CircuitPython_Karel_The_Robot/chapters/karel_ch08.json @@ -0,0 +1,41 @@ +{ + "input": { + "karel": { + "x": 0, + "y": 0, + "direction": "east" + }, + "world": [ + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 5, 5, 7], + [5, 5, 5, 5, 5, 4, 5, 5, 5, 7], + [5, 5, 4, 5, 5, 4, 5, 5, 5, 7], + [4, 5, 4, 5, 5, 4, 5, 5, 5, 7], + [4, 4, 4, 5, 4, 4, 5, 5, 5, 7], + [4, 4, 4, 4, 4, 4, 5, 4, 5, 7], + [4, 4, 4, 4, 4, 4, 5, 4, 5, 7] + ]}, + "goal": { + "karel": { + "x": 0, + "y": 0, + "direction": "east" + }, + "beeper_counts": { + "8, 0": 25 + }, + "world": [ + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 5, 5, 5, 5, 5, 7], + [5, 5, 5, 5, 5, 5, 5, 5, 5, 7], + [5, 5, 5, 5, 5, 5, 5, 5, 5, 7], + [5, 5, 5, 5, 5, 5, 5, 5, 5, 7], + [5, 5, 5, 5, 5, 5, 5, 5, 5, 7], + [5, 5, 5, 5, 5, 5, 5, 5, 5, 7], + [5, 5, 5, 5, 5, 5, 5, 5, 4, 7] + ]} +} \ No newline at end of file diff --git a/CircuitPython_Karel_The_Robot/chapters/karel_ch_template.json b/CircuitPython_Karel_The_Robot/chapters/karel_ch_template.json new file mode 100644 index 000000000..943f6c10b --- /dev/null +++ b/CircuitPython_Karel_The_Robot/chapters/karel_ch_template.json @@ -0,0 +1,38 @@ +{ + "input": { + "karel": { + "x": 0, + "y": 0, + "direction": "east" + }, + "world": [ + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 5, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 5, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 5, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 5, 7, 7, 7, 7, 7] + ]}, + "goal": { + "karel": { + "x": 0, + "y": 2, + "direction": "east" + }, + "world": [ + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [7, 7, 7, 7, 7, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 5, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 5, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 5, 7, 7, 7, 7, 7], + [5, 5, 5, 5, 5, 7, 7, 7, 7, 7] + ]} +} \ No newline at end of file diff --git a/CircuitPython_Karel_The_Robot/code.py b/CircuitPython_Karel_The_Robot/code.py new file mode 100644 index 000000000..d42bf2b5f --- /dev/null +++ b/CircuitPython_Karel_The_Robot/code.py @@ -0,0 +1,5 @@ +from karel.circuitpythonkarel import * + +def main(): + + ch_obj = load_state_file("chapters/karel_ch04.json") diff --git a/CircuitPython_Karel_The_Robot/karel/__init__.py b/CircuitPython_Karel_The_Robot/karel/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/CircuitPython_Karel_The_Robot/karel/circuitpythonkarel.py b/CircuitPython_Karel_The_Robot/karel/circuitpythonkarel.py new file mode 100644 index 000000000..a9830208d --- /dev/null +++ b/CircuitPython_Karel_The_Robot/karel/circuitpythonkarel.py @@ -0,0 +1,435 @@ +import json +import time + +import terminalio +from adafruit_display_text.bitmap_label import Label +import adafruit_imageload +import board +from displayio import Group, Bitmap, Palette, TileGrid + +EAST = 0 +NORTH = 1 +WEST = 2 +SOUTH = 3 + +DIRECTION_WORDS = ["east", "north", "west", "south"] + +DELAY = 0.2 + +TILE_SIZE = 24 + +COLOR_NAMES = [ + "white", + "black", + "red", + "orange", + "yellow", + "green", + "blue", + "purple", + "pink", + "light_gray", + "gray", + "brown", + "dark_green", + "turquoise", + "dark_blue", + "dark_red" +] +COLOR_VALUES = [ + 0xFFFFFF, + 0x000000, + 0xFF0000, + 0xFFA500, + 0xFFEE00, + 0x00C000, + 0x0000FF, + 0x8040C0, + 0xFF40C0, + 0xAAAAAA, + 0x444444, + 0xCA801D, + 0x008700, + 0x00C0C0, + 0x0000AA, + 0x800000 +] + + +class FrontIsBlocked(Exception): + pass + + +class BeeperNotPresent(Exception): + pass + + +class NoBeepersInBag(Exception): + pass + + +class Karel: + def __init__(self, spritesheet_bmp, spritesheet_palette, world_width=20, world_height=15): + + self.tilegrid = TileGrid(spritesheet_bmp, pixel_shader=spritesheet_palette, + default_tile=0, tile_width=TILE_SIZE, tile_height=TILE_SIZE) + self._direction = EAST + self.beeper_count = 0 + + @property + def direction(self): + return self._direction + + @direction.setter + def direction(self, new_value): + self._direction = new_value + if new_value == NORTH: + self.tilegrid[0, 0] = 1 + if new_value == EAST: + self.tilegrid[0, 0] = 0 + if new_value == SOUTH: + self.tilegrid[0, 0] = 3 + if new_value == WEST: + self.tilegrid[0, 0] = 2 + + @property + def x(self): + return self.tilegrid.x // TILE_SIZE + + @x.setter + def x(self, new_value): + self.tilegrid.x = new_value * TILE_SIZE + + @property + def y(self): + return self.tilegrid.y // TILE_SIZE + + @y.setter + def y(self, new_value): + self.tilegrid.y = new_value * TILE_SIZE + + +class World: + def __init__(self, display, world_width=10, world_height=10, beeper_limit=False): + print("world init()") + self.world_width = world_width + self.world_height = world_height + color_count = len(COLOR_NAMES) + self.background_bmp = Bitmap(world_width, world_height, color_count) + self.background_palette = Palette(color_count) + for i, color_val in enumerate(COLOR_VALUES): + self.background_palette[i] = color_val + self.background_tilegrid = TileGrid(bitmap=self.background_bmp, pixel_shader=self.background_palette) + self.background_group = Group(scale=TILE_SIZE) + self.background_group.append(self.background_tilegrid) + self.display = display + + self.world_group = Group() + self.world_group.append(self.background_group) + + lib_dir = "/".join(__file__.split("/")[0:3]) + # print(lib_dir) + self.spritesheet_bmp, self.spritesheet_palette = adafruit_imageload.load(f"{lib_dir}/spritesheet_24px.png") + self.spritesheet_palette.make_transparent(0) + + self.world_tilegrid = TileGrid(self.spritesheet_bmp, pixel_shader=self.spritesheet_palette, + tile_width=TILE_SIZE, tile_height=TILE_SIZE, width=20, height=15, default_tile=7) + + self.beeper_limit = beeper_limit + + self.beeper_count_labels = None + self._init_beeper_counts() + self.world_group.append(self.world_tilegrid) + + self.karel = Karel(self.spritesheet_bmp, self.spritesheet_palette) + self.world_group.append(self.karel.tilegrid) + + display.root_group = self.world_group + time.sleep(DELAY) + + def _init_beeper_counts(self): + if self.beeper_count_labels is not None: + for lbl in self.beeper_count_labels: + self.world_group.remove(lbl) + + self.beeper_count_labels = {} + self.beeper_counts = [] + for y in range(self.background_bmp.width): + self.beeper_counts.append([0 for x in range(self.background_bmp.width)]) + + def load_state(self, state_obj): + self._init_beeper_counts() + if "beeper_counts" in state_obj["input"]: + for beeper_count_loc_str in state_obj["input"]["beeper_counts"].keys(): + beeper_count_loc = [int(_) for _ in beeper_count_loc_str.split(",")] + print(beeper_count_loc) + self.beeper_counts[world.world_height - 1 - beeper_count_loc[1]][beeper_count_loc[0]] \ + = state_obj["input"]["beeper_counts"][beeper_count_loc_str] + for row in self.beeper_counts: + print(row) + update_beeper_count_labels() + + self.karel.x = state_obj["input"]["karel"]["x"] + self.karel.y = self.world_height - 1 - state_obj["input"]["karel"]["y"] + self.karel.direction = DIRECTION_WORDS.index(state_obj["input"]["karel"]["direction"]) + + for y, row in enumerate(state_obj["input"]["world"]): + for x, cell in enumerate(row): + self.world_tilegrid[x, y] = cell + + def check_goal_state(self, state_obj): + + if (self.world_height - 1 - self.karel.y) != state_obj["goal"]["karel"]["y"]: + print("karel y incorrect") + return False + if self.karel.x != state_obj["goal"]["karel"]["x"]: + print("karel x incorrect") + return False + if self.karel.direction != DIRECTION_WORDS.index(state_obj["goal"]["karel"]["direction"]): + print("karel dir incorrect") + return False + + if "beeper_counts" in state_obj["goal"]: + for beeper_count_loc_str in state_obj["goal"]["beeper_counts"].keys(): + beeper_count_loc = [int(_) for _ in beeper_count_loc_str.split(",")] + if self.beeper_counts[world.world_height - 1 - beeper_count_loc[1]][beeper_count_loc[0]] != \ + state_obj["goal"]["beeper_counts"][beeper_count_loc_str]: + print(f"beeper count incorrect {beeper_count_loc}") + return False + + for y in range(self.world_height): + for x in range(self.world_width): + + goal_cell_index = state_obj["goal"]["world"][y][x] + if self.world_tilegrid[x, y] != goal_cell_index: + print(f"world mismatch: {(x, y)}: {self.world_tilegrid[x, y]} != {goal_cell_index}") + return False + + # print(f"({x}, {y}) goal: {goal_cell_index} actual: {self.world_tilegrid[x, y]}") + # if goal_cell_index == 0: + # if self.karel.x != x or self.karel.y != y or self.karel.direction != EAST: + # return False + # elif goal_cell_index == 1: + # if self.karel.x != x or self.karel.y != y or self.karel.direction != NORTH: + # return False + # elif goal_cell_index == 2: + # if self.karel.x != x or self.karel.y != y or self.karel.direction != WEST: + # return False + # elif goal_cell_index == 3: + # if self.karel.x != x or self.karel.y != y or self.karel.direction != SOUTH: + # return False + # else: + # if self.world_tilegrid[x, y] != goal_cell_index: + # return False + return True + + +world = World(board.DISPLAY) + + +def move(): + print(f"Moving: {world.karel.direction}") + + if front_is_blocked(): + raise FrontIsBlocked("Karel can't move there") + + if world.karel.direction == EAST: + world.karel.x += 1 + if world.karel.direction == WEST: + world.karel.x -= 1 + + if world.karel.direction == NORTH: + world.karel.y -= 1 + if world.karel.direction == SOUTH: + world.karel.y += 1 + + time.sleep(DELAY) + + +def turn_left(): + if world.karel.direction == EAST: + world.karel.direction = NORTH + elif world.karel.direction == NORTH: + world.karel.direction = WEST + elif world.karel.direction == WEST: + world.karel.direction = SOUTH + elif world.karel.direction == SOUTH: + world.karel.direction = EAST + time.sleep(DELAY) + + +def corner_is_blocked(corner_x, corner_y): + corner_loc = [corner_x, corner_y] + if 0 > corner_loc[0] or 0 > corner_loc[1]: + return True + + if corner_loc[0] >= world.world_width or corner_loc[1] >= world.world_height: + return True + tile_index = world.world_tilegrid[corner_loc[0], corner_loc[1]] + if tile_index in (6, 7): + return True + + return False + + +def front_is_blocked(): + front_loc = [world.karel.x, world.karel.y] + if world.karel.direction == EAST: + front_loc[0] += 1 + if world.karel.direction == WEST: + front_loc[0] -= 1 + if world.karel.direction == NORTH: + front_loc[1] -= 1 + if world.karel.direction == SOUTH: + front_loc[1] += 1 + return corner_is_blocked(front_loc[0], front_loc[1]) + + +def right_is_blocked(): + right_loc = [world.karel.x, world.karel.y] + if world.karel.direction == EAST: + right_loc[1] += 1 + if world.karel.direction == WEST: + right_loc[1] -= 1 + if world.karel.direction == NORTH: + right_loc[0] += 1 + if world.karel.direction == SOUTH: + right_loc[0] -= 1 + return corner_is_blocked(right_loc[0], right_loc[1]) + + +def left_is_blocked(): + left_loc = [world.karel.x, world.karel.y] + if world.karel.direction == EAST: + left_loc[1] -= 1 + if world.karel.direction == WEST: + left_loc[1] += 1 + if world.karel.direction == NORTH: + left_loc[0] -= 1 + if world.karel.direction == SOUTH: + left_loc[0] += 1 + return corner_is_blocked(left_loc[0], left_loc[1]) + + +def paint_corner(color): + if color not in COLOR_NAMES: + raise ValueError(f"Color {color} is not valid. Supported colors are {COLOR_NAMES}") + print(f"name: {color} index: {COLOR_NAMES.index(color)}") + world.background_bmp[world.karel.x, world.karel.y] = COLOR_NAMES.index(color) + + +def update_beeper_count_labels(): + for y, row in enumerate(world.beeper_counts): + for x, count in enumerate(row): + if count <= 1: + if (x, y) in world.beeper_count_labels: + world.world_group.remove(world.beeper_count_labels[(x, y)]) + world.beeper_count_labels.pop((x, y)) + + else: + if (x, y) in world.beeper_count_labels: + world.beeper_count_labels[(x, y)].text = str(count) + else: + world.beeper_count_labels[(x, y)] = Label(terminalio.FONT, + text=str(count), + color=0x000000, + anchor_point=(0.5, 0.5), + anchored_position=(x * TILE_SIZE + TILE_SIZE // 2, + y * TILE_SIZE + TILE_SIZE // 2)) + world.world_group.append(world.beeper_count_labels[(x, y)]) + + +def pick_beeper(): + if not beepers_present(): + raise BeeperNotPresent("There is no beeper here") + + world.karel.beeper_count += 1 + + world.beeper_counts[world.karel.y][world.karel.x] = max(0, + world.beeper_counts[world.karel.y][world.karel.x] - 1) + update_beeper_count_labels() + if world.beeper_counts[world.karel.y][world.karel.x] == 0: + world.world_tilegrid[world.karel.x, world.karel.y] = 5 + time.sleep(DELAY) + + +def beepers_in_bag(): + return world.karel.beeper_count + + +def put_beeper(): + if beepers_in_bag() == 0 and world.beeper_limit: + raise NoBeepersInBag("There are no beepers in Karel's bag") + + world.karel.beeper_count -= 1 + world.beeper_counts[world.karel.y][world.karel.x] += 1 + update_beeper_count_labels() + world.world_tilegrid[world.karel.x, world.karel.y] = 4 + time.sleep(DELAY) + + +def beepers_present(): + tile_index = world.world_tilegrid[world.karel.x, world.karel.y] + if tile_index == 4: + return True + return False + + +def no_beepers_in_bag(): + return world.karel.beeper_count == 0 + + +def no_beepers_present(): + return not beepers_present() + + +def facing_north(): + return world.karel.direction == NORTH + + +def facing_east(): + return world.karel.direction == EAST + + +def facing_west(): + return world.karel.direction == WEST + + +def facing_south(): + return world.karel.direction == SOUTH + + +def not_facing_north(): + return not facing_north() + + +def not_facing_east(): + return not facing_east() + + +def not_facing_west(): + return not facing_west() + + +def not_facing_south(): + return not facing_south() + + +def left_is_clear(): + return not left_is_blocked() + + +def right_is_clear(): + return not right_is_blocked() + + +def front_is_clear(): + return not front_is_blocked() + +def load_state_file(state_filepath): + with open(state_filepath, "r") as f: + ch_obj = json.load(f) + world.load_state(ch_obj) + + time.sleep(DELAY) + return ch_obj \ No newline at end of file diff --git a/CircuitPython_Karel_The_Robot/karel/spritesheet.png b/CircuitPython_Karel_The_Robot/karel/spritesheet.png new file mode 100644 index 0000000000000000000000000000000000000000..9a40f6144bb35fbb7e94323aa9d5945fa4200bb2 GIT binary patch literal 4803 zcmeHLdsGuw8XrIeQR`!&z9^1CT@feq$dF`aNd-fMDA9;nAE=ed%mk+7F(hLWu!{IN ztEjcUmHO&dUD>YM;;ub{&-KwNzG}DYtF9KTVpT*>SA4E}Cqaa>J!g;S)c?pi$;^EB z`+oQPe&6rjGdBy&qtZJ^^^SrdsIxI6Eel+8z!wV*1Ha4tt0#lY-6G2bDU0#JqT6K? z>^v+LiagBw1seqUFD)M9aEAAbe0DFPs9n3af7I50HL_?<+<{MPE<2YGYtm}O&i)>i+vOxTkzrctnt0) z`Ddft`oCV8_s`I)8z04m?fFk!bf^AjPD#hQ;2GMUw@xm};ohsReg9_a=+7F*B-lUx z@sABBETvSv@6P<_E(;+jWUipsn~i$?%fdmq>t-y~ zWgJe4Jvw#LmccPGznib+wka>vxBa zP8=UGKDFyJsK6^`NlUxGSRI{x#4moo#Mc<-y9X8TJ89V!-+o&ezqxxszvWY6X77yr zq;FWy^e>NO&KMQFydidKW5fM_D^Kj&d*(S+v~t~XXk$t&Tgh~Dbv>pZN@%O@o zyRvsw+|WJlsHYtK+S_FMM+X(F;9;{C4IVM*@URu*7DxXk;nI@nkN)t^fehu^$pbL= zkWHa6%W5ND%(;4{>~XnKlMo$2PqjZ~qa*7>7neDT`(F0ewu?*-8=qZ0wLEOs#?9xm zv#&?iU2d=3F{x~C#N>KNKf033_%M3Ytur@E8dXoW4#E5#fBws!eMyZ4PoT}^pIz@P zijj+A22H`jqCrKiWqCTHb=~F3P?pze7C^y7ShpZb zg3AfZn2gmmP0}e8U>ts#pF=d6n&F+ECKdo6sGkv0T#2C$2ih{iBN@B^q$#0ajPO{% zdPcK&k87Hn2DXFrb}+gURJl(U}_DLAM3 zUkz9U2R~L~WHxb)id1QEOpR+*YAPvMb^vc2@Ad#C%9uE&RH*~ua$9In3?P<~bqW9i zc2Engck_(oa$8(3yG|iPz;a~sun8H-TuTx^PCh*oJCZqDU__C?V=>N1m=+I&x1=Iv>V1EYN zJ=(nAH*p5?eUqOixxL9LV7P6P*W$O0t~R<}i-Fg2Zc|qqU9ZK!YdN>6>sO;I>eY#n zcY+r^A2<(w-tAU*aF*;~&a@by7lCu-=NI?aB-YDDF=L_!f|T*{H^jeXs23O`B%{d? zQP-(!w;?e}{V@1PXJk^gV?t8Xur{_wD zu{>$j>gfklDrZ4AI<43|H|oKKSZE+`I8-;gHsN69%Bqv=^1_H-Dd7m@Fo)0DR`)Qn zbX>*nPnY;FLa5oB^PT2vYYw!j!>rC39Yai?l49cS?%PAOp-JkR^}QaPJGivM;QO|i zta`X|rG58V(ME+_DCh;Fr@q+#yfKg2Hl-3WqX+N1Q`RKX{tu{aDR+jYa@1lQ9 literal 0 HcmV?d00001 From 6e61f0003bfe34508e9f1b9439ac7059805e6025 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Tue, 17 Dec 2024 09:16:52 -0600 Subject: [PATCH 2/3] cleanup, format, pylint. update spritesheet. add stuff to code.py --- CircuitPython_Karel_The_Robot/code.py | 33 ++++- .../karel/circuitpythonkarel.py | 126 ++++++++++-------- .../karel/spritesheet.png | Bin 4803 -> 5034 bytes 3 files changed, 104 insertions(+), 55 deletions(-) diff --git a/CircuitPython_Karel_The_Robot/code.py b/CircuitPython_Karel_The_Robot/code.py index d42bf2b5f..a28f11d6a 100644 --- a/CircuitPython_Karel_The_Robot/code.py +++ b/CircuitPython_Karel_The_Robot/code.py @@ -1,5 +1,36 @@ +# SPDX-FileCopyrightText: 2024 Tim Cocks for Adafruit Industries +# +# SPDX-License-Identifier: MIT +""" +Karel the Robot code.py for devices with built-in display available +at board.DISPLAY. +""" +# pylint: disable=wildcard-import, unused-wildcard-import from karel.circuitpythonkarel import * + +# load a chapter. Edit the chapter filename to change chapters +# see available chapter files in chapters/ directory. +chapter_data = load_state_file("chapters/karel_ch01.json") + + def main(): + """ + Karel main() function declaration. + Put your code for Karel into this function. + """ + ## START OF MAIN FUNCTION, YOUR CODE GOES BELOW HERE ## + + + + ## END OF MAIN FUNCTION, YOUR CODE GOES ABOVE HERE ## + print(f"Goal state reached? {world.check_goal_state(chapter_data)}") + + +# call the main() function +main() - ch_obj = load_state_file("chapters/karel_ch04.json") +# Run forever so that the ending state of Karel and the world +# remains visible on the display. +while True: + pass diff --git a/CircuitPython_Karel_The_Robot/karel/circuitpythonkarel.py b/CircuitPython_Karel_The_Robot/karel/circuitpythonkarel.py index a9830208d..a91d8c3f4 100644 --- a/CircuitPython_Karel_The_Robot/karel/circuitpythonkarel.py +++ b/CircuitPython_Karel_The_Robot/karel/circuitpythonkarel.py @@ -1,3 +1,10 @@ +# SPDX-FileCopyrightText: 2024 Tim Cocks for Adafruit Industries +# +# SPDX-License-Identifier: MIT +""" +Karel the Robot helper class +""" + import json import time @@ -34,7 +41,7 @@ "dark_green", "turquoise", "dark_blue", - "dark_red" + "dark_red", ] COLOR_VALUES = [ 0xFFFFFF, @@ -52,7 +59,7 @@ 0x008700, 0x00C0C0, 0x0000AA, - 0x800000 + 0x800000, ] @@ -69,10 +76,15 @@ class NoBeepersInBag(Exception): class Karel: - def __init__(self, spritesheet_bmp, spritesheet_palette, world_width=20, world_height=15): - - self.tilegrid = TileGrid(spritesheet_bmp, pixel_shader=spritesheet_palette, - default_tile=0, tile_width=TILE_SIZE, tile_height=TILE_SIZE) + def __init__(self, spritesheet_bmp, spritesheet_palette): + + self.tilegrid = TileGrid( + spritesheet_bmp, + pixel_shader=spritesheet_palette, + default_tile=0, + tile_width=TILE_SIZE, + tile_height=TILE_SIZE, + ) self._direction = EAST self.beeper_count = 0 @@ -111,7 +123,6 @@ def y(self, new_value): class World: def __init__(self, display, world_width=10, world_height=10, beeper_limit=False): - print("world init()") self.world_width = world_width self.world_height = world_height color_count = len(COLOR_NAMES) @@ -119,7 +130,9 @@ def __init__(self, display, world_width=10, world_height=10, beeper_limit=False) self.background_palette = Palette(color_count) for i, color_val in enumerate(COLOR_VALUES): self.background_palette[i] = color_val - self.background_tilegrid = TileGrid(bitmap=self.background_bmp, pixel_shader=self.background_palette) + self.background_tilegrid = TileGrid( + bitmap=self.background_bmp, pixel_shader=self.background_palette + ) self.background_group = Group(scale=TILE_SIZE) self.background_group.append(self.background_tilegrid) self.display = display @@ -128,12 +141,20 @@ def __init__(self, display, world_width=10, world_height=10, beeper_limit=False) self.world_group.append(self.background_group) lib_dir = "/".join(__file__.split("/")[0:3]) - # print(lib_dir) - self.spritesheet_bmp, self.spritesheet_palette = adafruit_imageload.load(f"{lib_dir}/spritesheet_24px.png") + self.spritesheet_bmp, self.spritesheet_palette = adafruit_imageload.load( + f"{lib_dir}/spritesheet.png" + ) self.spritesheet_palette.make_transparent(0) - self.world_tilegrid = TileGrid(self.spritesheet_bmp, pixel_shader=self.spritesheet_palette, - tile_width=TILE_SIZE, tile_height=TILE_SIZE, width=20, height=15, default_tile=7) + self.world_tilegrid = TileGrid( + self.spritesheet_bmp, + pixel_shader=self.spritesheet_palette, + tile_width=TILE_SIZE, + tile_height=TILE_SIZE, + width=20, + height=15, + default_tile=7, + ) self.beeper_limit = beeper_limit @@ -154,24 +175,24 @@ def _init_beeper_counts(self): self.beeper_count_labels = {} self.beeper_counts = [] - for y in range(self.background_bmp.width): - self.beeper_counts.append([0 for x in range(self.background_bmp.width)]) + for _ in range(self.world_height): + self.beeper_counts.append([0 for x in range(self.world_width)]) def load_state(self, state_obj): self._init_beeper_counts() if "beeper_counts" in state_obj["input"]: for beeper_count_loc_str in state_obj["input"]["beeper_counts"].keys(): beeper_count_loc = [int(_) for _ in beeper_count_loc_str.split(",")] - print(beeper_count_loc) - self.beeper_counts[world.world_height - 1 - beeper_count_loc[1]][beeper_count_loc[0]] \ - = state_obj["input"]["beeper_counts"][beeper_count_loc_str] - for row in self.beeper_counts: - print(row) + self.beeper_counts[world.world_height - 1 - beeper_count_loc[1]][ + beeper_count_loc[0] + ] = state_obj["input"]["beeper_counts"][beeper_count_loc_str] update_beeper_count_labels() self.karel.x = state_obj["input"]["karel"]["x"] self.karel.y = self.world_height - 1 - state_obj["input"]["karel"]["y"] - self.karel.direction = DIRECTION_WORDS.index(state_obj["input"]["karel"]["direction"]) + self.karel.direction = DIRECTION_WORDS.index( + state_obj["input"]["karel"]["direction"] + ) for y, row in enumerate(state_obj["input"]["world"]): for x, cell in enumerate(row): @@ -185,15 +206,21 @@ def check_goal_state(self, state_obj): if self.karel.x != state_obj["goal"]["karel"]["x"]: print("karel x incorrect") return False - if self.karel.direction != DIRECTION_WORDS.index(state_obj["goal"]["karel"]["direction"]): + if self.karel.direction != DIRECTION_WORDS.index( + state_obj["goal"]["karel"]["direction"] + ): print("karel dir incorrect") return False if "beeper_counts" in state_obj["goal"]: for beeper_count_loc_str in state_obj["goal"]["beeper_counts"].keys(): beeper_count_loc = [int(_) for _ in beeper_count_loc_str.split(",")] - if self.beeper_counts[world.world_height - 1 - beeper_count_loc[1]][beeper_count_loc[0]] != \ - state_obj["goal"]["beeper_counts"][beeper_count_loc_str]: + if ( + self.beeper_counts[world.world_height - 1 - beeper_count_loc[1]][ + beeper_count_loc[0] + ] + != state_obj["goal"]["beeper_counts"][beeper_count_loc_str] + ): print(f"beeper count incorrect {beeper_count_loc}") return False @@ -202,25 +229,11 @@ def check_goal_state(self, state_obj): goal_cell_index = state_obj["goal"]["world"][y][x] if self.world_tilegrid[x, y] != goal_cell_index: - print(f"world mismatch: {(x, y)}: {self.world_tilegrid[x, y]} != {goal_cell_index}") + print( + f"world mismatch: {(x, world.world_height - 1 - y)}: " + + f"{self.world_tilegrid[x, y]} != {goal_cell_index}" + ) return False - - # print(f"({x}, {y}) goal: {goal_cell_index} actual: {self.world_tilegrid[x, y]}") - # if goal_cell_index == 0: - # if self.karel.x != x or self.karel.y != y or self.karel.direction != EAST: - # return False - # elif goal_cell_index == 1: - # if self.karel.x != x or self.karel.y != y or self.karel.direction != NORTH: - # return False - # elif goal_cell_index == 2: - # if self.karel.x != x or self.karel.y != y or self.karel.direction != WEST: - # return False - # elif goal_cell_index == 3: - # if self.karel.x != x or self.karel.y != y or self.karel.direction != SOUTH: - # return False - # else: - # if self.world_tilegrid[x, y] != goal_cell_index: - # return False return True @@ -228,8 +241,6 @@ def check_goal_state(self, state_obj): def move(): - print(f"Moving: {world.karel.direction}") - if front_is_blocked(): raise FrontIsBlocked("Karel can't move there") @@ -313,8 +324,9 @@ def left_is_blocked(): def paint_corner(color): if color not in COLOR_NAMES: - raise ValueError(f"Color {color} is not valid. Supported colors are {COLOR_NAMES}") - print(f"name: {color} index: {COLOR_NAMES.index(color)}") + raise ValueError( + f"Color {color} is not valid. Supported colors are {COLOR_NAMES}" + ) world.background_bmp[world.karel.x, world.karel.y] = COLOR_NAMES.index(color) @@ -330,12 +342,16 @@ def update_beeper_count_labels(): if (x, y) in world.beeper_count_labels: world.beeper_count_labels[(x, y)].text = str(count) else: - world.beeper_count_labels[(x, y)] = Label(terminalio.FONT, - text=str(count), - color=0x000000, - anchor_point=(0.5, 0.5), - anchored_position=(x * TILE_SIZE + TILE_SIZE // 2, - y * TILE_SIZE + TILE_SIZE // 2)) + world.beeper_count_labels[(x, y)] = Label( + terminalio.FONT, + text=str(count), + color=0x000000, + anchor_point=(0.5, 0.5), + anchored_position=( + x * TILE_SIZE + TILE_SIZE // 2, + y * TILE_SIZE + TILE_SIZE // 2, + ), + ) world.world_group.append(world.beeper_count_labels[(x, y)]) @@ -345,8 +361,9 @@ def pick_beeper(): world.karel.beeper_count += 1 - world.beeper_counts[world.karel.y][world.karel.x] = max(0, - world.beeper_counts[world.karel.y][world.karel.x] - 1) + world.beeper_counts[world.karel.y][world.karel.x] = max( + 0, world.beeper_counts[world.karel.y][world.karel.x] - 1 + ) update_beeper_count_labels() if world.beeper_counts[world.karel.y][world.karel.x] == 0: world.world_tilegrid[world.karel.x, world.karel.y] = 5 @@ -426,10 +443,11 @@ def right_is_clear(): def front_is_clear(): return not front_is_blocked() + def load_state_file(state_filepath): with open(state_filepath, "r") as f: ch_obj = json.load(f) world.load_state(ch_obj) time.sleep(DELAY) - return ch_obj \ No newline at end of file + return ch_obj diff --git a/CircuitPython_Karel_The_Robot/karel/spritesheet.png b/CircuitPython_Karel_The_Robot/karel/spritesheet.png index 9a40f6144bb35fbb7e94323aa9d5945fa4200bb2..f8bac206846a4a5e080330248f342dd2e1fc5cc6 100644 GIT binary patch delta 1118 zcmV-k1fl!GC8{ToBmwS`B`SYJIgb1BlHQ=l@2uk6Zj&Y@al(u&jBGl;K40nM3T~XV z)Mjo*2z7PtNE*%924>QMBP_1KA9|8?!H_Nzf^+C6bmTd>$B?}0SEH5Wj;!1ly@$R% z^(`85``suUNS>4Fh!3KXa5&P*_i$w1>f>q0PS0rfQK@Xja#f%*)oM+SyfJCTK99@j zYiA#g%3SDMSbUW-Jn<=62qS zJNhI3^Q`m@DF1f5qb6HklNtdae^aF*RS`RgIAo|!c2N<>T7@E12(?114knj=L6e3g z#l=x@EjakGSaoo5*44pP5ClI!oE@ALU8KbSC509-9vt`M-Mz=%J3weum}Ygw0Zq5f zbTT1kbE{(L6=4jbA2CE_W*Kvml!EX0x<`PocQKyjf9}uGr{*mN1VrLEe=|&*c!PLm z(>6Ho6GvD{R*BDvCrr8^@gvt2kKZ^KT^4v|#LT4Ui6g{fv4fQkW+hW2o+gf}nojvb z)?=0P7H6$eW37Ag7l!lt$}-n!jv|RgEJ1<@1vQjWflYmtp_5`EP5TKS|A_0C$fc00 z3`ULxRG~q3{osG_yIZR;e>LePg%d#ci{pHZ0ij)>S$CZ8W5;Qp0KsSAN^kqC4Pf?@ z^m<#19svW}z{Pc2Q}%$%9bov$kWJZ@f;5Ff0eC;7Z^{8fw?OZj*IR2Jrw>4ex=P&u z2Zz9Tk+Ro)-rdvL+rMX8{rv#bk8;h2lhr%`01rNCR9JLaO-wptv$q0)0wgszVPY^i zF*q$XVKQMYG&DIiEnzb>FfC(dVl-l7FgZD8Vlk6k1*i-(G&VRfF*GnWG&M4l5C(Ax zH&ieO9?krFgQ9iHaa!4o(OLU1e*&8NRtr}H3$(7E;FUy ztAvwI5h#Bo}Hv5xpq=;%aA~mXu3{_L&3EFko33`J2JG_92lg85#z=Y#cF!ROyD@g*U^iZr k7JS?NBmwP_B`SXwrmoHnL8WQ?@R@Y@VHPFi4?M{#Frc0U;2ih`9C41^V@Y29YtRaEL$uw6)&k$3 z_#Okf{vH$zB+t!s#t$(_I2h^7k6>h8%j0V2K~JmqQ7LSj<)ZM)REkVF;>x52dY+x= z>tG*)wkhZvSovyYaNp3h_Ddgh3Z1e&o9B@*C%Z!+xF_Hqxni;xMsLXk)pJStqs!_f_ z68V=dPe{I zLrQ-i(3-Dv-2q9dHI|oqz(Bfy0Okyoq=X9c*c<>RWktd0g5xQ`x|O@koM;0w89)Us z0BukOfT-y92#Qv+RnCEU*#Iw4c3{;v$YOtB0H6tg4M+A)Hm6dF^&~Ros0oZXFATQ0azWw)TVW?fY08lT$@p3?zD>`_5IjBJF zAV0sC2(xT(0KG2}#>C(nNAF97K|~xpdS4>a321@*>|I5&iYrvLA d%W!^uegIp_q2ZXDe#rm;002ovPDHLkV1g|T+&lmP From 4f2193e3c51c8e2c33437ca62b9b368193186e8c Mon Sep 17 00:00:00 2001 From: foamyguy Date: Tue, 17 Dec 2024 09:27:27 -0600 Subject: [PATCH 3/3] re-arrange condition, add license to __init__ --- CircuitPython_Karel_The_Robot/karel/__init__.py | 3 +++ CircuitPython_Karel_The_Robot/karel/circuitpythonkarel.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CircuitPython_Karel_The_Robot/karel/__init__.py b/CircuitPython_Karel_The_Robot/karel/__init__.py index e69de29bb..ed2a9d7a3 100644 --- a/CircuitPython_Karel_The_Robot/karel/__init__.py +++ b/CircuitPython_Karel_The_Robot/karel/__init__.py @@ -0,0 +1,3 @@ +# SPDX-FileCopyrightText: 2024 Tim Cocks for Adafruit Industries +# +# SPDX-License-Identifier: MIT diff --git a/CircuitPython_Karel_The_Robot/karel/circuitpythonkarel.py b/CircuitPython_Karel_The_Robot/karel/circuitpythonkarel.py index a91d8c3f4..58319f499 100644 --- a/CircuitPython_Karel_The_Robot/karel/circuitpythonkarel.py +++ b/CircuitPython_Karel_The_Robot/karel/circuitpythonkarel.py @@ -271,7 +271,7 @@ def turn_left(): def corner_is_blocked(corner_x, corner_y): corner_loc = [corner_x, corner_y] - if 0 > corner_loc[0] or 0 > corner_loc[1]: + if corner_loc[0] < 0 or corner_loc[1] < 0: return True if corner_loc[0] >= world.world_width or corner_loc[1] >= world.world_height: