Add more levels and introduce NOT gate with single input

This commit is contained in:
csd4ni3l
2025-10-14 18:23:41 +02:00
parent b02b192f93
commit ab9035e76d
3 changed files with 123 additions and 24 deletions

View File

@@ -1,11 +1,11 @@
import arcade, arcade.gui, random, datetime, os, json import arcade, arcade.gui, random, datetime, os, json
from utils.utils import cubic_bezier_points, get_gate_port_position, generate_task_text
from utils.constants import button_style, dropdown_style, LOGICAL_GATES, LEVELS
from utils.preload import button_texture, button_hovered_texture
from datetime import datetime from datetime import datetime
from utils.utils import cubic_bezier_points, get_gate_port_position, generate_task_text
from utils.constants import button_style, dropdown_style, LOGICAL_GATES, LEVELS, SINGLE_INPUT_LOGICAL_GATES
from utils.preload import button_texture, button_hovered_texture
class LogicalGate(arcade.gui.UIBoxLayout): class LogicalGate(arcade.gui.UIBoxLayout):
def __init__(self, id, x, y, gate_type, value): def __init__(self, id, x, y, gate_type, value):
super().__init__(x=x, y=y, space_between=2, vertical=False) super().__init__(x=x, y=y, space_between=2, vertical=False)
@@ -34,6 +34,8 @@ class LogicalGate(arcade.gui.UIBoxLayout):
self.value = self.input[0].calculate_value() self.value = self.input[0].calculate_value()
elif self.gate_type == "INPUT": # dont set INPUT to None elif self.gate_type == "INPUT": # dont set INPUT to None
pass pass
elif self.gate_type in SINGLE_INPUT_LOGICAL_GATES and len(self.input) == 1:
self.value = int(LOGICAL_GATES[self.gate_type](self.input[0].calculate_value()))
elif len(self.input) == 2: elif len(self.input) == 2:
self.value = int(LOGICAL_GATES[self.gate_type](self.input[0].calculate_value(), self.input[1].calculate_value())) # have to convert to int cause it might return boolean self.value = int(LOGICAL_GATES[self.gate_type](self.input[0].calculate_value(), self.input[1].calculate_value())) # have to convert to int cause it might return boolean
else: else:
@@ -179,7 +181,9 @@ class Game(arcade.gui.UIView):
else: else:
process_nodes.remove(requirement[1]) process_nodes.remove(requirement[1])
if not self.level_num in self.data["completed_levels"]:
self.data["completed_levels"].append(self.level_num) self.data["completed_levels"].append(self.level_num)
self.task_label.text = f"You Successfully Completed Level {self.level_num + 1}!" self.task_label.text = f"You Successfully Completed Level {self.level_num + 1}!"
with open("data.json", "w") as file: with open("data.json", "w") as file:
@@ -193,7 +197,9 @@ class Game(arcade.gui.UIView):
self.selected_input = None self.selected_input = None
def select_input(self, gate_id): def select_input(self, gate_id):
if len(self.gates[gate_id].input) == 2: if self.gates[gate_id].gate_type not in SINGLE_INPUT_LOGICAL_GATES and len(self.gates[gate_id].input) == 2:
return
elif self.gates[gate_id].gate_type in SINGLE_INPUT_LOGICAL_GATES and len(self.gates[gate_id].input) == 1:
return return
if self.selected_output is not None: if self.selected_output is not None:

View File

@@ -36,23 +36,23 @@ class LevelSelector(arcade.gui.UIView):
for n in range(len(LEVELS)): for n in range(len(LEVELS)):
row, col = n // 5, n % 5 row, col = n // 5, n % 5
if n < 5: if n < 8:
difficulty = "Easy" difficulty = "Easy"
elif n < 15: elif n < 21:
difficulty = "Intermediate" difficulty = "Intermediate"
elif n < 20: elif n < 30:
difficulty = "Hard" difficulty = "Hard"
else: else:
difficulty = "Extra Hard" difficulty = "Extra Hard"
completed_notice = '\n(Completed)' if n in self.data['completed_levels'] else '' completed_notice = '\n(Completed)' if n in self.data['completed_levels'] else ''
level_button = self.grid.add(arcade.gui.UITextureButton(width=self.window.width / 8, height=self.window.height / 8, text=f"{difficulty} Level {n + 1}{completed_notice}", texture=button_texture, texture_hovered=button_hovered_texture, style=button_style, multiline=True), row=row, column=col) level_button = self.grid.add(arcade.gui.UITextureButton(width=self.window.width / 8, height=self.window.height / 12, text=f"{difficulty} Level {n + 1}{completed_notice}", texture=button_texture, texture_hovered=button_hovered_texture, style=button_style, multiline=True), row=row, column=col)
level_button.on_click = lambda event, n=n: self.play(n) level_button.on_click = lambda event, n=n: self.play(n)
row, col = (n + 1) // 5, (n + 1) % 5 row, col = (n + 1) // 5, (n + 1) % 5
diy_button = self.anchor.add(arcade.gui.UITextureButton(width=self.window.width / 2, height=self.window.height / 8, text=f"DIY", texture=button_texture, texture_hovered=button_hovered_texture, style=button_style), anchor_x="center", anchor_y="bottom", align_y=20) diy_button = self.anchor.add(arcade.gui.UITextureButton(width=self.window.width / 2, height=self.window.height / 10, text=f"DIY", texture=button_texture, texture_hovered=button_hovered_texture, style=button_style), anchor_x="center", anchor_y="bottom", align_y=10)
diy_button.on_click = lambda event: self.play(-1) diy_button.on_click = lambda event: self.play(-1)
self.grid._trigger_size_hint_update() self.grid._trigger_size_hint_update()

View File

@@ -7,6 +7,8 @@ menu_background_color = (30, 30, 47)
log_dir = 'logs' log_dir = 'logs'
discord_presence_id = 1427213145667276840 discord_presence_id = 1427213145667276840
SINGLE_INPUT_LOGICAL_GATES = ["NOT"]
LOGICAL_GATES = { LOGICAL_GATES = {
"AND": lambda a, b: a and b, "AND": lambda a, b: a and b,
"OR": lambda a, b: a or b, "OR": lambda a, b: a or b,
@@ -14,11 +16,11 @@ LOGICAL_GATES = {
"NOR": lambda a, b: not (a or b), "NOR": lambda a, b: not (a or b),
"XOR": lambda a, b: a != b, "XOR": lambda a, b: a != b,
"XNOR": lambda a, b: a == b, "XNOR": lambda a, b: a == b,
"NOT": lambda a: not a,
} }
LEVELS = [ LEVELS = [
# EASY # EASY
[ [
[2, "INPUT", 1], [2, "INPUT", 1],
[1, "AND"], [1, "AND"],
@@ -30,6 +32,11 @@ LEVELS = [
[1, "OR"], [1, "OR"],
[1, "OUTPUT", 1] [1, "OUTPUT", 1]
], ],
[
[1, "INPUT", 1],
[1, "NOT"],
[1, "OUTPUT", 0]
],
[ [
[2, "INPUT", 1], [2, "INPUT", 1],
[1, "NAND"], [1, "NAND"],
@@ -41,6 +48,13 @@ LEVELS = [
[1, "XOR"], [1, "XOR"],
[1, "OUTPUT", 1] [1, "OUTPUT", 1]
], ],
[
[1, "INPUT", 0],
[1, "INPUT", 1],
[1, "NOT"],
[1, "AND"],
[1, "OUTPUT", 1]
],
[ [
[2, "INPUT", 1], [2, "INPUT", 1],
[1, "INPUT", 0], [1, "INPUT", 0],
@@ -48,9 +62,13 @@ LEVELS = [
[1, "OR"], [1, "OR"],
[1, "OUTPUT", 1] [1, "OUTPUT", 1]
], ],
[
[2, "INPUT", 1],
[1, "NOT"],
[1, "NAND"],
[1, "OUTPUT", 1]
],
# INTERMEDIATE # INTERMEDIATE
[ [
[2, "INPUT", 0], [2, "INPUT", 0],
[1, "INPUT", 1], [1, "INPUT", 1],
@@ -65,6 +83,13 @@ LEVELS = [
[1, "OR"], [1, "OR"],
[1, "OUTPUT", 1] [1, "OUTPUT", 1]
], ],
[
[1, "INPUT", 1],
[1, "INPUT", 0],
[1, "NOT"],
[1, "XOR"],
[1, "OUTPUT", 0]
],
[ [
[2, "INPUT", 1], [2, "INPUT", 1],
[2, "INPUT", 0], [2, "INPUT", 0],
@@ -73,6 +98,14 @@ LEVELS = [
[1, "XOR"], [1, "XOR"],
[1, "OUTPUT", 0] [1, "OUTPUT", 0]
], ],
[
[2, "INPUT", 0],
[1, "INPUT", 1],
[1, "NOT"],
[1, "NOR"],
[1, "OR"],
[1, "OUTPUT", 1]
],
[ [
[3, "INPUT", 1], [3, "INPUT", 1],
[1, "INPUT", 0], [1, "INPUT", 0],
@@ -86,6 +119,14 @@ LEVELS = [
[1, "AND"], [1, "AND"],
[1, "OUTPUT", 1] [1, "OUTPUT", 1]
], ],
[
[2, "INPUT", 1],
[1, "INPUT", 0],
[1, "NOT"],
[1, "AND"],
[1, "NAND"],
[1, "OUTPUT", 0]
],
[ [
[2, "INPUT", 1], [2, "INPUT", 1],
[2, "INPUT", 0], [2, "INPUT", 0],
@@ -110,8 +151,9 @@ LEVELS = [
[1, "OUTPUT", 1] [1, "OUTPUT", 1]
], ],
[ [
[4, "INPUT", 0],
[1, "INPUT", 1], [1, "INPUT", 1],
[3, "INPUT", 0],
[1, "NOT"],
[2, "OR"], [2, "OR"],
[1, "NAND"], [1, "NAND"],
[1, "OUTPUT", 0] [1, "OUTPUT", 0]
@@ -124,9 +166,16 @@ LEVELS = [
[1, "AND"], [1, "AND"],
[1, "OUTPUT", 0] [1, "OUTPUT", 0]
], ],
# HARD # HARD
[
[3, "INPUT", 1],
[1, "INPUT", 0],
[1, "NOT"],
[1, "AND"],
[1, "OR"],
[1, "XOR"],
[1, "OUTPUT", 0]
],
[ [
[3, "INPUT", 1], [3, "INPUT", 1],
[2, "INPUT", 0], [2, "INPUT", 0],
@@ -136,6 +185,14 @@ LEVELS = [
[1, "XOR"], [1, "XOR"],
[1, "OUTPUT", 1] [1, "OUTPUT", 1]
], ],
[
[2, "INPUT", 1],
[2, "INPUT", 0],
[2, "NOT"],
[1, "NAND"],
[1, "OR"],
[1, "OUTPUT", 1]
],
[ [
[2, "INPUT", 1], [2, "INPUT", 1],
[2, "INPUT", 0], [2, "INPUT", 0],
@@ -143,6 +200,15 @@ LEVELS = [
[1, "OR"], [1, "OR"],
[1, "OUTPUT", 0] [1, "OUTPUT", 0]
], ],
[
[3, "INPUT", 0],
[1, "INPUT", 1],
[1, "NOT"],
[2, "NOR"],
[1, "XOR"],
[1, "XNOR"],
[1, "OUTPUT", 1]
],
[ [
[4, "INPUT", 0], [4, "INPUT", 0],
[2, "INPUT", 1], [2, "INPUT", 1],
@@ -160,6 +226,15 @@ LEVELS = [
[1, "XOR"], [1, "XOR"],
[1, "OUTPUT", 0] [1, "OUTPUT", 0]
], ],
[
[2, "INPUT", 1],
[3, "INPUT", 0],
[1, "NOT"],
[2, "XOR"],
[1, "NAND"],
[1, "NOR"],
[1, "OUTPUT", 0]
],
[ [
[4, "INPUT", 1], [4, "INPUT", 1],
[2, "INPUT", 0], [2, "INPUT", 0],
@@ -169,9 +244,7 @@ LEVELS = [
[1, "XNOR"], [1, "XNOR"],
[1, "OUTPUT", 1] [1, "OUTPUT", 1]
], ],
# EXTRA HARD
# Extra Hard
[ [
[2, "INPUT", 1], [2, "INPUT", 1],
[2, "INPUT", 0], [2, "INPUT", 0],
@@ -182,6 +255,16 @@ LEVELS = [
[1, "OUTPUT", 0], [1, "OUTPUT", 0],
[1, "OUTPUT", 1] [1, "OUTPUT", 1]
], ],
[
[2, "INPUT", 1],
[1, "INPUT", 0],
[1, "NOT"],
[1, "AND"],
[1, "OR"],
[1, "XOR"],
[1, "OUTPUT", 0],
[1, "OUTPUT", 1]
],
[ [
[3, "INPUT", 1], [3, "INPUT", 1],
[3, "INPUT", 0], [3, "INPUT", 0],
@@ -192,6 +275,16 @@ LEVELS = [
[1, "OUTPUT", 1], [1, "OUTPUT", 1],
[1, "OUTPUT", 0] [1, "OUTPUT", 0]
], ],
[
[2, "INPUT", 1],
[2, "INPUT", 0],
[2, "NOT"],
[1, "NAND"],
[1, "NOR"],
[1, "XOR"],
[1, "OUTPUT", 1],
[1, "OUTPUT", 0]
],
[ [
[4, "INPUT", 1], [4, "INPUT", 1],
[2, "INPUT", 0], [2, "INPUT", 0],
@@ -199,7 +292,7 @@ LEVELS = [
[2, "XNOR"], [2, "XNOR"],
[1, "AND"], [1, "AND"],
[1, "OR"], [1, "OR"],
[2, "OUTPUT", 1], [2, "OUTPUT", 1]
], ],
[ [
[3, "INPUT", 1], [3, "INPUT", 1],