+69
-2
nilla.nix
+69
-2
nilla.nix
···
14
14
inputs = {
15
15
nixpkgs = {
16
16
src = pins.nixpkgs;
17
-
};
17
+
};
18
+
};
19
+
packages.cmu-graphics = {
20
+
systems = [ "x86_64-linux" ];
21
+
package =
22
+
{
23
+
pkgs,
24
+
python313,
25
+
fetchPypi
26
+
}:
27
+
let
28
+
pname = "cmu_graphics";
29
+
version = "1.1.43";
30
+
in
31
+
python313.pkgs.buildPythonPackage {
32
+
inherit pname version;
33
+
34
+
src = fetchPypi {
35
+
inherit pname version;
36
+
hash = "sha256-IU6z+4xB7Uz/SsIrFkFRfLL10ZmpQTPyK+yDWDq89Xs=";
37
+
};
38
+
39
+
doCheck = false;
40
+
checkPhase = ''
41
+
true
42
+
'';
43
+
dontCheckPythonPackages = true;
44
+
pyproject = true;
45
+
46
+
dependencies = [
47
+
python313.pkgs.pycairo
48
+
python313.pkgs.pygame
49
+
];
50
+
51
+
build-system = [
52
+
python313.pkgs.setuptools
53
+
python313.pkgs.wheel
54
+
pkgs.pre-commit
55
+
];
56
+
57
+
};
18
58
};
19
59
shells.default = config.shells.python;
20
60
shells.python = {
21
61
# Declare what systems the shell can be used on.
22
62
systems = [ "x86_64-linux" ];
23
-
63
+
24
64
# Define our shell environment.
25
65
shell =
26
66
{
···
34
74
pkgs.black
35
75
];
36
76
};
77
+
};
78
+
shells.cmu-graphics = {
79
+
systems = [ "x86_64-linux" ];
80
+
shell =
81
+
{
82
+
pkgs,
83
+
mkShell,
84
+
...
85
+
}:
86
+
let
87
+
python3 = pkgs.python313.override {
88
+
packageOverrides = pyfinal: pyprev: {
89
+
cmu_graphics = config.packages.cmu-graphics.result.x86_64-linux;
90
+
};
91
+
};
92
+
in
93
+
mkShell {
94
+
packages = [
95
+
(python3.withPackages (ppkgs: [
96
+
ppkgs.cmu_graphics
97
+
ppkgs.pycairo
98
+
ppkgs.pygame
99
+
ppkgs.pillow
100
+
ppkgs.numpy
101
+
]))
102
+
];
103
+
};
37
104
};
38
105
};
39
106
}
+167
python/oct6/memorygame/main.py
+167
python/oct6/memorygame/main.py
···
1
+
from cmu_graphics.cmu_graphics import AppWrapper, app, runApp
2
+
from cmu_graphics import *
3
+
from types import SimpleNamespace
4
+
from random import randint, choice
5
+
from time import sleep
6
+
from sys import exit
7
+
8
+
9
+
def onAppStart(app_inst: AppWrapper):
10
+
app_inst.difficulty = 1
11
+
pairs = 5 * app_inst.difficulty
12
+
app_inst.dots = []
13
+
for i in range(10 * app_inst.difficulty):
14
+
app_inst.dots.append(makeDot(app_inst, i % pairs))
15
+
app_inst.counter = 0
16
+
app_inst.showing = []
17
+
app_inst.end_game = False
18
+
app_inst.hint = False
19
+
app_inst.hints = 0
20
+
app_inst.warning = 0
21
+
22
+
23
+
def checkOverlap(dot1, dots):
24
+
for dot2 in dots:
25
+
if (dot1.cx - dot2.cx) ** 2 + (dot1.cy - dot2.cy) ** 2 <= (
26
+
dot1.r + dot2.r
27
+
) ** 2:
28
+
return True
29
+
return False
30
+
31
+
32
+
def makeDot(app_inst: AppWrapper, num: int):
33
+
dot = SimpleNamespace()
34
+
dot.num = num
35
+
dot.r = randint(10, 30)
36
+
dot.cx = 0
37
+
dot.cy = 0
38
+
while dot.cx == 0 or dot.cy == 0 or checkOverlap(dot, app_inst.dots):
39
+
dot.cx = randint(20, app_inst.width - 20)
40
+
dot.cy = randint(20, app_inst.height - 20)
41
+
42
+
dot.color = choice(["aqua", "lime", "yellow"])
43
+
return dot
44
+
45
+
46
+
def drawDot(dot: SimpleNamespace):
47
+
drawCircle(dot.cx, dot.cy, dot.r, fill=dot.color)
48
+
49
+
50
+
def collision(pointer, dot2):
51
+
if (pointer.cx - dot2.cx) ** 2 + (pointer.cy - dot2.cy) ** 2 <= dot2.r**2:
52
+
return True
53
+
return False
54
+
55
+
56
+
def onMousePress(app_inst: AppWrapper, mouseX, mouseY):
57
+
pointer = SimpleNamespace()
58
+
pointer.cx = mouseX
59
+
pointer.cy = mouseY
60
+
for dot in app_inst.dots:
61
+
if collision(pointer, dot):
62
+
app_inst.showing.append(dot)
63
+
64
+
65
+
def onStep(app_inst: AppWrapper):
66
+
if app_inst.warning != 0:
67
+
sleep(2)
68
+
app_inst.warning = 0
69
+
if app_inst.hint:
70
+
sleep(2)
71
+
app_inst.hint = False
72
+
if len(app_inst.showing) == 2:
73
+
if app_inst.showing[0].num == app_inst.showing[1].num:
74
+
app_inst.dots.remove(app_inst.showing[0])
75
+
app_inst.dots.remove(app_inst.showing[1])
76
+
sleep(0.5)
77
+
app_inst.counter += 1
78
+
app_inst.showing = []
79
+
if len(app_inst.dots) == 0:
80
+
app_inst.end_game = True
81
+
82
+
83
+
def onKeyPress(app_inst: AppWrapper, key):
84
+
if key == "r":
85
+
app_inst.dots = []
86
+
for i in range(10):
87
+
app_inst.dots.append(makeDot(app_inst, i))
88
+
app_inst.showing = []
89
+
app_inst.counter = 0
90
+
app_inst.end_game = False
91
+
elif key == "q":
92
+
exit()
93
+
elif key == "h":
94
+
app_inst.hint = True
95
+
app_inst.hints += 1
96
+
elif key.isdigit():
97
+
if int(key) < 1 or int(key) > 4:
98
+
app_inst.warning = int(key)
99
+
app_inst.difficulty = max(1, min(int(key), 4))
100
+
pairs = 5 * app_inst.difficulty
101
+
app_inst.dots = []
102
+
for i in range(10 * app_inst.difficulty):
103
+
app_inst.dots.append(makeDot(app_inst, i % pairs))
104
+
app_inst.counter = 0
105
+
app_inst.showing = []
106
+
app_inst.end_game = False
107
+
108
+
109
+
def redrawAll(app_inst: AppWrapper):
110
+
if app_inst.warning:
111
+
drawLabel(
112
+
f"Invalid difficulty: {app_inst.warning}",
113
+
app_inst.width // 2,
114
+
app_inst.height // 2 - 50,
115
+
size=20,
116
+
)
117
+
drawLabel(
118
+
"difficulty must be between 1 and 4",
119
+
app_inst.width // 2,
120
+
app_inst.height // 2 - 25,
121
+
size=20,
122
+
)
123
+
drawLabel(
124
+
f"picking difficulty {app_inst.difficulty}",
125
+
app_inst.width // 2,
126
+
app_inst.height // 2,
127
+
size=20,
128
+
)
129
+
return
130
+
for dot in app_inst.dots:
131
+
drawDot(dot)
132
+
if dot in app_inst.showing:
133
+
drawLabel(str(dot.num), dot.cx, dot.cy, size=24)
134
+
elif app_inst.hint:
135
+
drawLabel(str(dot.num), dot.cx, dot.cy, size=24)
136
+
if app_inst.end_game:
137
+
drawLabel("You win!", app_inst.width // 2, app_inst.height // 2 - 50, size=36)
138
+
drawLabel(
139
+
f"Final score: {app_inst.counter}",
140
+
app_inst.width // 2,
141
+
app_inst.height // 2,
142
+
size=24,
143
+
)
144
+
drawLabel(
145
+
f"Hints used: {app_inst.hints}",
146
+
app_inst.width // 2,
147
+
app_inst.height // 2 + 25,
148
+
size=24,
149
+
)
150
+
drawLabel(
151
+
"Press 'r' to restart",
152
+
app_inst.width // 2,
153
+
app_inst.height // 2 + 75,
154
+
size=24,
155
+
)
156
+
drawLabel(
157
+
"Press 'q' to quit",
158
+
app_inst.width // 2,
159
+
app_inst.height // 2 + 100,
160
+
size=24,
161
+
)
162
+
else:
163
+
drawLabel(f"{app_inst.counter}", 20, 20, size=24, fill="blue")
164
+
drawLabel(f"{app_inst.hints}", app_inst.width - 20, 20, size=24, fill="red")
165
+
166
+
167
+
runApp()