Skip to content

Improve Corner Colors - BLANK enum and restore on reset #85

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion stanfordkarel/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from stanfordkarel.stanfordkarel import ( # noqa: F401
from stanfordkarel.karel_world import ( # noqa: F401
BLACK,
BLANK,
BLUE,
Expand All @@ -13,6 +13,8 @@
RED,
WHITE,
YELLOW,
)
from stanfordkarel.stanfordkarel import ( # noqa: F401
beepers_in_bag,
beepers_present,
corner_color_is,
Expand Down
6 changes: 3 additions & 3 deletions stanfordkarel/karel_ascii.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from enum import Enum, unique
from typing import Any, Dict, Iterator, Tuple

from .karel_world import Direction, KarelWorld
from .karel_world import BLANK, Direction, KarelWorld

CHAR_WIDTH = 5
HORIZONTAL, VERTICAL = "─", "│"
Expand All @@ -25,15 +25,15 @@ def __init__(self, value: str = "·") -> None:
self.value = value
self.walls: list[Direction] = []
self.beepers = 0
self.color = ""
self.color = BLANK

def __repr__(self) -> str:
result = ""
if self.value == "K" and self.beepers > 0:
result = "<K>"
elif self.beepers > 0:
result = f"<{self.beepers}>"
elif self.color:
elif self.color != BLANK:
result = self.color[:3]
else:
result = self.value
Expand Down
3 changes: 2 additions & 1 deletion stanfordkarel/karel_program.py
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ def paint_corner(self, color: str) -> None:
This function makes Karel paint its current corner the indicated color.
This function will raise a KarelException if the indicated color is not one
of the valid predefined colors. For this list of colors, check the
kareldefinitions.py file.
stanfordkarel.py file.

Parameters:
color (str) - The color string specifying which color to paint the corner
Expand All @@ -392,6 +392,7 @@ def paint_corner(self, color: str) -> None:
f"Karel attempted to paint the corner with color {color}, "
"which is not valid.",
)

self.world.paint_corner(self.avenue, self.street, color)

def corner_color_is(self, color: str) -> bool:
Expand Down
64 changes: 44 additions & 20 deletions stanfordkarel/karel_world.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,20 +49,38 @@
from typing import Any, NamedTuple

INFINITY = -1

# Defined constants for ease of use by students when coloring corners
BLANK = ""
RED = "Red"
BLACK = "Black"
CYAN = "Cyan"
DARK_GRAY = "Dark Gray"
GRAY = "Gray"
GREEN = "Green"
LIGHT_GRAY = "Light Gray"
MAGENTA = "Magenta"
ORANGE = "Orange"
PINK = "Pink"
WHITE = "White"
BLUE = "Blue"
YELLOW = "Yellow"

COLOR_MAP = {
"Red": "red",
"Black": "black",
"Cyan": "cyan",
"Dark Gray": "gray30",
"Gray": "gray55",
"Green": "green",
"Light Gray": "gray80",
"Magenta": "magenta3",
"Orange": "orange",
"Pink": "pink",
"White": "snow",
"Blue": "blue",
"Yellow": "yellow",
BLANK: "",
BLACK: "black",
BLUE: "blue",
CYAN: "cyan",
DARK_GRAY: "gray30",
GRAY: "gray55",
GREEN: "green",
LIGHT_GRAY: "gray80",
MAGENTA: "magenta3",
ORANGE: "orange",
PINK: "pink",
RED: "red",
WHITE: "snow",
YELLOW: "yellow",
}
INIT_SPEED = 50
VALID_WORLD_KEYWORDS = [
Expand Down Expand Up @@ -91,7 +109,7 @@ def __init__(self, world_file: str) -> None:
# Map of beeper locations to the count of beepers at that location
self.beepers: dict[tuple[int, int], int] = {}

# Map of corner colors, defaults to ""
# Map of corner colors
self.corner_colors: dict[tuple[int, int], str] = {}

# Set of Wall objects placed in the world
Expand All @@ -116,6 +134,14 @@ def __init__(self, world_file: str) -> None:
# Save initial beeper state to enable world reset
self.init_beepers = copy.deepcopy(self.beepers)

# Fill corner colors
for ave in range(1, 1 + self.num_avenues):
for st in range(1, 1 + self.num_streets):
if (ave, st) not in self.corner_colors:
self.corner_colors[(ave, st)] = BLANK

self.init_corner_colors = copy.deepcopy(self.corner_colors)

def __eq__(self, other: object) -> bool:
if isinstance(other, KarelWorld):
return (
Expand Down Expand Up @@ -317,13 +343,11 @@ def paint_corner(self, avenue: int, street: int, color: str) -> None:
self.corner_colors[(avenue, street)] = color

def corner_color(self, avenue: int, street: int) -> str:
if (avenue, street) in self.corner_colors:
return self.corner_colors[(avenue, street)]
return ""
return self.corner_colors[(avenue, street)]

def reset_corner(self, avenue: int, street: int) -> None:
self.beepers[(avenue, street)] = 0
self.corner_colors[(avenue, street)] = ""
self.corner_colors[(avenue, street)] = BLANK

def wall_exists(self, avenue: int, street: int, direction: Direction) -> bool:
wall = Wall(avenue, street, direction)
Expand All @@ -335,7 +359,7 @@ def in_bounds(self, avenue: int, street: int) -> bool:
def reset_world(self) -> None:
"""Reset initial state of beepers in the world"""
self.beepers = copy.deepcopy(self.init_beepers)
self.corner_colors = {}
self.corner_colors = copy.deepcopy(self.init_corner_colors)

def reload_world(self, filename: str | None = None) -> None:
"""Reloads world using constructor."""
Expand All @@ -357,7 +381,7 @@ def save_to_file(self, filepath: Path) -> None:

# Next, output all color information
for (x, y), color in sorted(self.corner_colors.items()):
if color:
if color is not BLANK:
output += f"Color: ({x}, {y}); {color}\n"

# Next, output Karel information
Expand Down
17 changes: 0 additions & 17 deletions stanfordkarel/stanfordkarel.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,23 +123,6 @@ def corner_color_is(color: str) -> bool:
return True


# Defined constants for ease of use by students when coloring corners
RED = "Red"
BLACK = "Black"
CYAN = "Cyan"
DARK_GRAY = "Dark Gray"
GRAY = "Gray"
GREEN = "Green"
LIGHT_GRAY = "Light Gray"
MAGENTA = "Magenta"
ORANGE = "Orange"
PINK = "Pink"
WHITE = "White"
BLUE = "Blue"
YELLOW = "Yellow"
BLANK = ""


def run_karel_program(world_file: str = "") -> None:
# Extract the name of the file the student is executing
student_code_file = Path(sys.argv[0])
Expand Down
19 changes: 19 additions & 0 deletions tests/karel_world_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from stanfordkarel.karel_application import StudentCode
from stanfordkarel.karel_program import KarelProgram
from stanfordkarel.karel_world import BLANK, RED

STONE_MASON_ASCII_OUTPUT = (
"┌───────────────────────────────────────────────────────────────────────────────┐",
Expand Down Expand Up @@ -133,3 +134,21 @@ def test_equal_worlds() -> None:
ref_program = KarelProgram("1x1")

assert ref_program.world == test_program.world

@staticmethod
def test_paint_corner_blank() -> None:
test_program = KarelProgram("1x1")
test_program.paint_corner(BLANK)
ref_program = KarelProgram("1x1")

assert ref_program.world == test_program.world

@staticmethod
def test_corner_color_world_reset() -> None:
test_program = KarelProgram("1x1")
test_program.paint_corner(RED)
test_program.world.reset_world()

ref_program = KarelProgram("1x1")

assert ref_program.world == test_program.world
Loading