Skip to content

Commit

Permalink
🪲 If-pressed fixes (#5980)
Browse files Browse the repository at this point in the history
This PR addresses multiple issues with if-pressed not working with other code structures, e.g. list access, in/not in operator, for cycle.

The major technical change in this PR that list access instances are no longer stored and treated as variables in the lookup. Consider the program: `animals is cat, dog\nprint animals at 1`. Before, the lookup table would hold two variables: `animals` and `animals[int(1)-1]`. Now, it will only hold the variable `animals` and registers the occurrence of `animals[int(1)-1]` as variable access.

Fixes #5955

**How to test**
The following code snippets should work. Use them as starting points for further testing.
```
# level 9
points = 0
letters = a, b, c, d, e
repeat 10 times
    letter = letters at random
    print 'Press the letter ' letter
    if letter is pressed
        print 'great'
        points = points + 1
    else
        print 'oops wrong letter'
        points = points - 2

print points
```

```
# level 17
# Make 2 lists
colors = ['red','yellow','green','blue']
simon_sequence = []
player_sequence = []

# Create a function that adds a color
define add_random_color:
    color = colors[random]
    add color to simon_sequence

# Create a function that shows the simon_sequence
define show_simon_sequence with level:
    for i in range 1 to level:
        print simon_sequence[i]
        sleep 1
        clear

# Create a function that creates the player_sequence
define get_answer with level:
    for i in range 1 to level:
        print 'What is color number ' i '?'
        print 'press (r)ed, (y)ellow, (g)reen or (b)lue'
        if r is pressed:
            answer = 'red'
        elif y is pressed:
            answer = 'yellow'
        elif g is pressed:
            answer = 'green'
        elif b is pressed:
            answer = 'blue'
        else:
            print 'press (r)ed, (y)ellow, (g)reen or (b)lue'
        add answer to player_sequence


# Set up
level = 1
game_over = False
print 'Welcome to Simon Says!'
sleep 1
clear

# The game
while game_over == False:
    print 'this is level ' level
    sleep 1
    clear
    player_sequence = []

    call add_random_color
    call show_simon_sequence with level
    call get_answer with level
    if player_sequence == simon_sequence:
        print 'Well done!'
        sleep 1
        level = level + 1
    else:
        print 'Helaas pindakaas'
        game_over = True
```
  • Loading branch information
boryanagoncharenko authored Dec 6, 2024
1 parent 5308864 commit c339053
Show file tree
Hide file tree
Showing 7 changed files with 1,338 additions and 156 deletions.
351 changes: 196 additions & 155 deletions hedy.py

Large diffs are not rendered by default.

96 changes: 96 additions & 0 deletions tests/test_level/test_level_05.py
Original file line number Diff line number Diff line change
Expand Up @@ -1421,6 +1421,102 @@ def if_pressed_else_():

self.multi_level_tester(code=code, expected=expected, max_level=7)

def test_if_pressed_with_random_list_access(self):
code = textwrap.dedent("""\
letters is a, b, c, d, e
print letters at random
if x is pressed print 'great' else print 'not great'""")

expected = textwrap.dedent('''\
global_scope_ = dict()
global_scope_["letters"] = ['a', 'b', 'c', 'd', 'e']
try:
random.choice(global_scope_.get("letters") or letters)
except IndexError:
raise Exception("""Runtime Index Error""")
print(f'{random.choice(global_scope_.get("letters") or letters)}')
if_pressed_mapping = {"else": "if_pressed_default_else"}
if_pressed_mapping['x'] = 'if_pressed_x_'
if_pressed_mapping['else'] = 'if_pressed_else_'
def if_pressed_x_():
print(f'great')
def if_pressed_else_():
print(f'not great')
extensions.if_pressed(if_pressed_mapping)''')

self.single_level_tester(code=code, expected=expected)

def test_if_pressed_with_index_list_access(self):
code = textwrap.dedent("""\
letters is a, b, c, d, e
print letters at 1
if x is pressed print 'great' else print 'not great'""")

expected = textwrap.dedent('''\
global_scope_ = dict()
global_scope_["letters"] = ['a', 'b', 'c', 'd', 'e']
try:
(global_scope_.get("letters") or letters)[int(1)-1]
except IndexError:
raise Exception("""Runtime Index Error""")
print(f'{(global_scope_.get("letters") or letters)[int(1)-1]}')
if_pressed_mapping = {"else": "if_pressed_default_else"}
if_pressed_mapping['x'] = 'if_pressed_x_'
if_pressed_mapping['else'] = 'if_pressed_else_'
def if_pressed_x_():
print(f'great')
def if_pressed_else_():
print(f'not great')
extensions.if_pressed(if_pressed_mapping)''')

self.single_level_tester(code=code, expected=expected)

def test_if_pressed_with_index_var_list_access(self):
code = textwrap.dedent("""\
letters is a, b, c, d, e
index is 3
let is letters at index
if x is pressed print 'x' else print 'y'""")

expected = textwrap.dedent('''\
global_scope_ = dict()
global_scope_["letters"] = ['a', 'b', 'c', 'd', 'e']
global_scope_["index"] = '3'
try:
(global_scope_.get("letters") or letters)[int(global_scope_.get("index") or index)-1]
except IndexError:
raise Exception("""Runtime Index Error""")
global_scope_["let"] = (global_scope_.get("letters") or letters)[int(global_scope_.get("index") or index)-1]
if_pressed_mapping = {"else": "if_pressed_default_else"}
if_pressed_mapping['x'] = 'if_pressed_x_'
if_pressed_mapping['else'] = 'if_pressed_else_'
def if_pressed_x_():
print(f'x')
def if_pressed_else_():
print(f'y')
extensions.if_pressed(if_pressed_mapping)''')

self.single_level_tester(code=code, expected=expected, unused_allowed=True)

def test_if_pressed_with_ask(self):
code = textwrap.dedent("""\
a is ask 'question'
if x is pressed print 'x' else print 'y'""")

expected = textwrap.dedent('''\
global_scope_ = dict()
global_scope_["a"] = input(f'question')
if_pressed_mapping = {"else": "if_pressed_default_else"}
if_pressed_mapping['x'] = 'if_pressed_x_'
if_pressed_mapping['else'] = 'if_pressed_else_'
def if_pressed_x_():
print(f'x')
def if_pressed_else_():
print(f'y')
extensions.if_pressed(if_pressed_mapping)''')

self.single_level_tester(code=code, expected=expected, unused_allowed=True)

def test_if_pressed_missing_else_gives_error(self):
code = textwrap.dedent("""\
prind skipping
Expand Down
190 changes: 190 additions & 0 deletions tests/test_level/test_level_06.py
Original file line number Diff line number Diff line change
Expand Up @@ -2750,3 +2750,193 @@ def if_pressed_else_():
print(f'{global_scope_.get("m") or m}')""")

self.multi_level_tester(code=code, expected=expected, max_level=7)

def test_if_pressed_with_random_list_access(self):
code = textwrap.dedent("""\
letters is a, b, c, d, e
print letters at random
if x is pressed print 'great' else print 'not great'""")

expected = textwrap.dedent('''\
global_scope_ = dict()
global_scope_["letters"] = Value([Value('a'), Value('b'), Value('c'), Value('d'), Value('e')])
try:
random.choice((global_scope_.get("letters") or letters).data)
except IndexError:
raise Exception("""Runtime Index Error""")
print(f'{random.choice((global_scope_.get("letters") or letters).data)}')
if_pressed_mapping = {"else": "if_pressed_default_else"}
if_pressed_mapping['x'] = 'if_pressed_x_'
if_pressed_mapping['else'] = 'if_pressed_else_'
def if_pressed_x_():
print(f'great')
def if_pressed_else_():
print(f'not great')
extensions.if_pressed(if_pressed_mapping)''')

self.multi_level_tester(code=code, expected=expected, max_level=7)

def test_if_pressed_with_index_list_access(self):
code = textwrap.dedent("""\
letters is a, b, c, d, e
print letters at 1
if x is pressed print 'great' else print 'not great'""")

expected = textwrap.dedent('''\
global_scope_ = dict()
global_scope_["letters"] = Value([Value('a'), Value('b'), Value('c'), Value('d'), Value('e')])
try:
(global_scope_.get("letters") or letters).data[int(1)-1]
except IndexError:
raise Exception("""Runtime Index Error""")
print(f'{(global_scope_.get("letters") or letters).data[int(1)-1]}')
if_pressed_mapping = {"else": "if_pressed_default_else"}
if_pressed_mapping['x'] = 'if_pressed_x_'
if_pressed_mapping['else'] = 'if_pressed_else_'
def if_pressed_x_():
print(f'great')
def if_pressed_else_():
print(f'not great')
extensions.if_pressed(if_pressed_mapping)''')

self.multi_level_tester(code=code, expected=expected, max_level=7)

def test_if_pressed_with_index_var_list_access(self):
code = textwrap.dedent("""\
opt is a, b, c
i is 3
a is opt at i
if x is pressed print 'x' else print 'y'""")

expected = textwrap.dedent('''\
global_scope_ = dict()
global_scope_["opt"] = Value([Value('a'), Value('b'), Value('c')])
global_scope_["i"] = Value('3', num_sys='Latin')
try:
(global_scope_.get("opt") or opt).data[int((global_scope_.get("i") or i).data)-1]
except IndexError:
raise Exception("""Runtime Index Error""")
global_scope_["a"] = (global_scope_.get("opt") or opt).data[int((global_scope_.get("i") or i).data)-1]
if_pressed_mapping = {"else": "if_pressed_default_else"}
if_pressed_mapping['x'] = 'if_pressed_x_'
if_pressed_mapping['else'] = 'if_pressed_else_'
def if_pressed_x_():
print(f'x')
def if_pressed_else_():
print(f'y')
extensions.if_pressed(if_pressed_mapping)''')

self.multi_level_tester(code=code, expected=expected, max_level=7, unused_allowed=True)

def test_if_pressed_add_to_list(self):
code = textwrap.dedent("""\
colors is red, blue
if g is pressed answer is green else answer is wrong
add answer to colors""")

expected = textwrap.dedent('''\
global_scope_ = dict()
global_scope_["colors"] = Value([Value('red'), Value('blue')])
if_pressed_mapping = {"else": "if_pressed_default_else"}
if_pressed_mapping['g'] = 'if_pressed_g_'
if_pressed_mapping['else'] = 'if_pressed_else_'
def if_pressed_g_():
global_scope_["answer"] = Value('green')
def if_pressed_else_():
global_scope_["answer"] = Value('wrong')
extensions.if_pressed(if_pressed_mapping)
(global_scope_.get("colors") or colors).data.append(global_scope_.get("answer") or answer)''')

self.multi_level_tester(code=code, expected=expected, max_level=7)

def test_if_pressed_remove_from_list(self):
code = textwrap.dedent("""\
colors is red, blue
if g is pressed answer is green else answer is wrong
remove answer from colors""")

expected = textwrap.dedent('''\
global_scope_ = dict()
global_scope_["colors"] = Value([Value('red'), Value('blue')])
if_pressed_mapping = {"else": "if_pressed_default_else"}
if_pressed_mapping['g'] = 'if_pressed_g_'
if_pressed_mapping['else'] = 'if_pressed_else_'
def if_pressed_g_():
global_scope_["answer"] = Value('green')
def if_pressed_else_():
global_scope_["answer"] = Value('wrong')
extensions.if_pressed(if_pressed_mapping)
try:
(global_scope_.get("colors") or colors).data.remove(global_scope_.get("answer") or answer)
except:
pass''')

self.multi_level_tester(code=code, expected=expected, max_level=7)

def test_if_pressed_with_ask(self):
code = textwrap.dedent("""\
a is ask 'question'
if x is pressed print 'x' else print 'y'""")

expected = textwrap.dedent('''\
global_scope_ = dict()
global_scope_["a"] = input(f'question')
__ns = get_num_sys(global_scope_.get("a") or a)
global_scope_["a"] = Value(global_scope_.get("a") or a, num_sys=__ns)
if_pressed_mapping = {"else": "if_pressed_default_else"}
if_pressed_mapping['x'] = 'if_pressed_x_'
if_pressed_mapping['else'] = 'if_pressed_else_'
def if_pressed_x_():
print(f'x')
def if_pressed_else_():
print(f'y')
extensions.if_pressed(if_pressed_mapping)''')

self.multi_level_tester(code=code, expected=expected, max_level=7, unused_allowed=True)

def test_if_pressed_with_calc(self):
code = textwrap.dedent("""\
points = 0
if x is pressed points = 1 + 1 else points = 5 - 2
print points""")

p = 'global_scope_.get("points") or points'
expected = textwrap.dedent(f'''\
global_scope_ = dict()
global_scope_["points"] = Value('0', num_sys='Latin')
if_pressed_mapping = {{"else": "if_pressed_default_else"}}
if_pressed_mapping['x'] = 'if_pressed_x_'
if_pressed_mapping['else'] = 'if_pressed_else_'
def if_pressed_x_():
global_scope_["points"] = Value(1 + 1, num_sys='Latin')
def if_pressed_else_():
global_scope_["points"] = Value(5 - 2, num_sys='Latin')
extensions.if_pressed(if_pressed_mapping)
print(f'{{{p}}}')''')

self.multi_level_tester(code=code, expected=expected, max_level=7)

def test_if_pressed_with_calc_var(self):
code = textwrap.dedent("""\
points = 0
if x is pressed points = points + 1 else points = points - 2
print points""")

p = 'global_scope_.get("points") or points'
points = f'number_with_error({p}, """Runtime Value Error""")'
one = 'number_with_error(1, """Runtime Value Error""")'
two = 'number_with_error(2, """Runtime Value Error""")'
expected = textwrap.dedent(f'''\
global_scope_ = dict()
global_scope_["points"] = Value('0', num_sys='Latin')
if_pressed_mapping = {{"else": "if_pressed_default_else"}}
if_pressed_mapping['x'] = 'if_pressed_x_'
if_pressed_mapping['else'] = 'if_pressed_else_'
def if_pressed_x_():
global_scope_["points"] = Value({points} + {one}, num_sys=get_num_sys({p}))
def if_pressed_else_():
global_scope_["points"] = Value({points} - {two}, num_sys=get_num_sys({p}))
extensions.if_pressed(if_pressed_mapping)
print(f'{{{p}}}')''')

self.multi_level_tester(code=code, expected=expected, max_level=7)
Loading

0 comments on commit c339053

Please sign in to comment.