Загрузка данных
"""
СИМУЛЯТОР ШАУРМИСТА — RELEASE BUILD v1.1
Герои: Камаладдин и Оглы
Один файл. Вся графика рисуется кодом.
"""
import pygame, sys, random, math, json, os
pygame.init()
W, H = 1280, 720
screen = pygame.display.set_mode((W, H))
pygame.display.set_caption("Симулятор Шаурмиста: Камаладдин и Оглы")
clock = pygame.time.Clock()
# ============================== ШРИФТЫ ==============================
font_xs = pygame.font.SysFont("consolas", 12)
font_s = pygame.font.SysFont("consolas", 15)
font_m = pygame.font.SysFont("consolas", 19, bold=True)
font_l = pygame.font.SysFont("consolas", 26, bold=True)
font_xl = pygame.font.SysFont("consolas", 44, bold=True)
font_xxl= pygame.font.SysFont("consolas", 66, bold=True)
# ============================== ЦВЕТА ==============================
C_NIGHT = (18, 16, 28)
C_BG = (30, 28, 42)
C_PANEL = (44, 42, 58)
C_PANEL_D = (28, 26, 40)
C_PANEL_L = (60, 58, 78)
C_TEXT = (242, 236, 220)
C_TEXT_DIM = (160, 156, 145)
C_GOLD = (248, 200, 80)
C_GOLD_D = (180, 140, 50)
C_RED = (230, 80, 80)
C_RED_D = (150, 40, 40)
C_GREEN = (110, 210, 120)
C_GREEN_D = (50, 130, 60)
C_BLUE = (100, 170, 240)
C_PURPLE = (170, 120, 220)
C_ORANGE = (245, 140, 50)
C_SKIN = (222, 184, 135)
C_SKIN_D = (180, 140, 95)
C_HAIR = (40, 30, 25)
C_LAVASH = (240, 220, 170)
C_TOM = (220, 70, 60)
# ============================== ИНГРЕДИЕНТЫ ==============================
(I_LAVASH, I_MEAT_C, I_MEAT_B, I_TOMATO, I_CUCUMBER, I_CABBAGE,
I_ONION, I_CHEESE, I_FRIES, I_SAUCE_G, I_SAUCE_S, I_WRAP) = range(12)
ING_NAME = {
I_LAVASH:"Лаваш", I_MEAT_C:"Курица", I_MEAT_B:"Говядина",
I_TOMATO:"Помидор", I_CUCUMBER:"Огурец", I_CABBAGE:"Капуста",
I_ONION:"Лук", I_CHEESE:"Сыр", I_FRIES:"Картофель фри",
I_SAUCE_G:"Чесночный", I_SAUCE_S:"Острый", I_WRAP:"Завернуть",
}
ING_SHORT = {
I_LAVASH:"Лаваш", I_MEAT_C:"Курица", I_MEAT_B:"Говядина",
I_TOMATO:"Помидор", I_CUCUMBER:"Огурец", I_CABBAGE:"Капуста",
I_ONION:"Лук", I_CHEESE:"Сыр", I_FRIES:"Фри",
I_SAUCE_G:"Чеснок", I_SAUCE_S:"Острый", I_WRAP:"Завернуть",
}
GRILL_INGS = {I_MEAT_C, I_MEAT_B, I_FRIES}
COOK_TIME = {I_MEAT_C: 4.0, I_MEAT_B: 6.0, I_FRIES: 3.0}
BURN_TIME = {I_MEAT_C: 3.5, I_MEAT_B: 4.5, I_FRIES: 2.5}
# ============================== РИСОВАНИЕ ЕДЫ ==============================
def draw_food(surf, ing, x, y, size, cook_state=None):
cx, cy = x + size // 2, y + size // 2
r = size // 2 - 3
if ing == I_LAVASH:
pygame.draw.ellipse(surf, C_LAVASH, (x+4, y+12, size-8, size-24))
pygame.draw.ellipse(surf, (200,180,130), (x+4, y+12, size-8, size-24), 2)
pygame.draw.ellipse(surf, (215,195,150), (x+8, y+16, size-16, size-30))
elif ing == I_MEAT_C:
col = (240,210,140)
if cook_state == "cooked": col = (200,140,60)
if cook_state == "burned": col = (60,40,30)
pygame.draw.ellipse(surf, col, (x+8, y+14, size-16, size-28))
dark = (max(0,col[0]-50), max(0,col[1]-50), max(0,col[2]-50))
pygame.draw.ellipse(surf, dark, (x+8, y+14, size-16, size-28), 2)
for i in range(3):
pygame.draw.line(surf, (250,230,180),
(x+16+i*7, y+20), (x+16+i*7, y+size-20), 2)
elif ing == I_MEAT_B:
col = (160,70,50)
if cook_state == "cooked": col = (120,50,30)
if cook_state == "burned": col = (50,30,25)
pygame.draw.ellipse(surf, col, (x+8, y+14, size-16, size-28))
dark = (max(0,col[0]-30), max(0,col[1]-20), max(0,col[2]-20))
pygame.draw.ellipse(surf, dark, (x+8, y+14, size-16, size-28), 2)
for i in range(3):
pygame.draw.line(surf, (200,110,80),
(x+16+i*7, y+20), (x+16+i*7, y+size-20), 2)
elif ing == I_TOMATO:
pygame.draw.circle(surf, C_TOM, (cx, cy), r-3)
pygame.draw.circle(surf, (150,25,25), (cx, cy), r-3, 2)
pygame.draw.circle(surf, (255,130,120), (cx-4, cy-4), 4)
elif ing == I_CUCUMBER:
pygame.draw.ellipse(surf, (140,200,100), (cx-10, y+8, 20, size-16))
pygame.draw.ellipse(surf, (60,130,50), (cx-10, y+8, 20, size-16), 2)
pygame.draw.circle(surf, (170,220,130), (cx, y+18), 2)
pygame.draw.circle(surf, (170,220,130), (cx, y+34), 2)
elif ing == I_CABBAGE:
pygame.draw.circle(surf, (200,230,180), (cx, cy), r-4)
for a in range(6):
ang = a * math.pi / 3
ex = cx + math.cos(ang) * (r-8)
ey = cy + math.sin(ang) * (r-8)
pygame.draw.line(surf, (130,170,100), (cx, cy), (ex, ey), 1)
pygame.draw.circle(surf, (130,170,100), (cx, cy), r-4, 2)
elif ing == I_ONION:
for i, rr in enumerate([r-2, r-8, r-14]):
col = (230,220,200) if i % 2 == 0 else (210,200,180)
pygame.draw.arc(surf, col, (cx-rr, cy-rr, rr*2, rr*2), 0, math.pi, 3)
pygame.draw.arc(surf, col, (cx-rr, cy-rr, rr*2, rr*2), math.pi, 2*math.pi, 3)
elif ing == I_CHEESE:
pygame.draw.polygon(surf, (250,210,100), [
(cx-16, cy+12), (cx+18, cy+12), (cx+18, cy-4), (cx-10, cy-14)])
pygame.draw.polygon(surf, (200,150,40), [
(cx-16, cy+12), (cx+18, cy+12), (cx+18, cy-4), (cx-10, cy-14)], 2)
for dx, dy in [(-4,0),(4,4),(-2,6),(8,-2)]:
pygame.draw.circle(surf, (230,180,60), (cx+dx, cy+dy), 2)
elif ing == I_FRIES:
col = (250,210,130)
if cook_state == "cooked": col = (250,180,80)
if cook_state == "burned": col = (90,60,30)
for i in range(6):
xx = x + 14 + i * 6
yy = y + 20 + (i % 2) * 2
pygame.draw.rect(surf, col, (xx, yy, 4, 24))
pygame.draw.rect(surf, (200,60,40), (x+12, y+40, size-24, 12))
pygame.draw.rect(surf, (140,30,20), (x+12, y+40, size-24, 12), 2)
elif ing == I_SAUCE_G:
pygame.draw.rect(surf, (240,235,220), (x+14, y+14, size-28, size-24))
pygame.draw.rect(surf, (170,160,140), (x+14, y+14, size-28, size-24), 2)
pygame.draw.circle(surf, (200,190,170), (cx, cy-2), 5)
elif ing == I_SAUCE_S:
pygame.draw.rect(surf, (220,60,40), (x+14, y+14, size-28, size-24))
pygame.draw.rect(surf, (140,30,20), (x+14, y+14, size-28, size-24), 2)
pygame.draw.circle(surf, (255,200,180), (cx, cy-2), 5)
elif ing == I_WRAP:
pygame.draw.polygon(surf, C_LAVASH, [
(x+10, y+size-8), (x+size-10, y+size-8), (cx, y+8)])
pygame.draw.polygon(surf, (180,160,120), [
(x+10, y+size-8), (x+size-10, y+size-8), (cx, y+8)], 2)
pygame.draw.line(surf, (150,130,100), (cx, y+size-14), (cx, y+14), 2)
pygame.draw.rect(surf, C_PANEL_D, (x, y, size, size), 2)
# ============================== ПЕРСОНАЖИ ==============================
def draw_kama(surf, x, y, scale=1.0, mood="normal", frame=0, action=None):
s = scale
def R(c, rect):
pygame.draw.rect(surf, c,
(x + int(rect[0]*s), y + int(rect[1]*s),
max(1, int(rect[2]*s)), max(1, int(rect[3]*s))))
leg_off = int(math.sin(frame*0.1) * 3) if action == "walk" else 0
R((50,50,90), (30, 190+leg_off, 22, 40))
R((50,50,90), (58, 190-leg_off, 22, 40))
R((30,30,50), (28, 226+leg_off, 26, 10))
R((30,30,50), (56, 226-leg_off, 26, 10))
shirt = (70, 100, 180)
if mood == "sad": shirt = (60, 70, 140)
R(shirt, (28, 118, 64, 78))
for i in range(4):
R((50,80,150), (28, 130+i*16, 64, 3))
R((240,240,240), (36, 140, 48, 60))
R((220,220,220), (46, 165, 28, 20))
R((220,220,220), (36, 115, 48, 6))
arm_off = int(math.sin(frame*0.15) * 5) if action == "cook" else 0
R(C_SKIN, (16, 122, 14, 50+arm_off))
R(C_SKIN_D, (16, 168+arm_off, 14, 8))
R(C_SKIN, (90, 122, 14, 50-arm_off))
R(C_SKIN_D, (90, 168-arm_off, 14, 8))
R(C_SKIN_D, (50, 108, 22, 14))
pygame.draw.ellipse(surf, C_SKIN,
(x + int(36*s), y + int(40*s), int(48*s), int(74*s)))
pygame.draw.ellipse(surf, C_SKIN_D,
(x + int(36*s), y + int(40*s), int(48*s), int(74*s)), max(1, int(2*s)))
R(C_SKIN, (32, 68, 8, 12))
R(C_SKIN, (80, 68, 8, 12))
pygame.draw.arc(surf, C_HAIR,
(x + int(32*s), y + int(30*s), int(56*s), int(80*s)),
0.15, math.pi - 0.15, int(14*s))
R(C_HAIR, (34, 42, 52, 22))
R(C_HAIR, (56, 30, 10, 12))
eye_y = 72
if mood == "sad":
R(C_HAIR, (42, eye_y-4, 10, 3))
R(C_HAIR, (66, eye_y-4, 10, 3))
elif mood == "happy":
pygame.draw.arc(surf, C_HAIR,
(x + int(42*s), y + int(eye_y*s), int(14*s), int(10*s)),
math.pi, 2*math.pi, max(1, int(3*s)))
pygame.draw.arc(surf, C_HAIR,
(x + int(64*s), y + int(eye_y*s), int(14*s), int(10*s)),
math.pi, 2*math.pi, max(1, int(3*s)))
elif mood == "surprised":
pygame.draw.circle(surf, (255,255,255),
(x + int(48*s), y + int((eye_y+4)*s)), int(7*s))
pygame.draw.circle(surf, (255,255,255),
(x + int(72*s), y + int((eye_y+4)*s)), int(7*s))
pygame.draw.circle(surf, C_HAIR,
(x + int(48*s), y + int((eye_y+4)*s)), int(3*s))
pygame.draw.circle(surf, C_HAIR,
(x + int(72*s), y + int((eye_y+4)*s)), int(3*s))
else:
pygame.draw.circle(surf, (255,255,255),
(x + int(48*s), y + int((eye_y+4)*s)), int(6*s))
pygame.draw.circle(surf, (255,255,255),
(x + int(72*s), y + int((eye_y+4)*s)), int(6*s))
pygame.draw.circle(surf, (30,60,100),
(x + int(49*s), y + int((eye_y+4)*s)), int(3*s))
pygame.draw.circle(surf, (30,60,100),
(x + int(73*s), y + int((eye_y+4)*s)), int(3*s))
R(C_SKIN_D, (58, eye_y+10, 4, 8))
R(C_HAIR, (48, eye_y+22, 24, 4))
R(C_HAIR, (46, eye_y+21, 28, 2))
R(C_HAIR, (44, eye_y+26, 6, 3))
R(C_HAIR, (70, eye_y+26, 6, 3))
if mood == "happy":
pygame.draw.arc(surf, (120,50,50),
(x + int(52*s), y + int((eye_y+28)*s), int(20*s), int(10*s)),
0, math.pi, max(1, int(2*s)))
elif mood == "sad":
pygame.draw.arc(surf, (120,50,50),
(x + int(52*s), y + int((eye_y+34)*s), int(20*s), int(10*s)),
math.pi, 2*math.pi, max(1, int(2*s)))
else:
R((120,50,50), (54, eye_y+32, 16, 2))
def draw_ogly(surf, x, y, scale=1.0, mood="normal", frame=0, action=None):
s = scale
def R(c, rect):
pygame.draw.rect(surf, c,
(x + int(rect[0]*s), y + int(rect[1]*s),
max(1, int(rect[2]*s)), max(1, int(rect[3]*s))))
leg_off = int(math.sin(frame*0.1) * 3) if action == "walk" else 0
R((40,40,60), (26, 195+leg_off, 26, 42))
R((40,40,60), (58, 195-leg_off, 26, 42))
R((20,20,30), (22, 232+leg_off, 32, 10))
R((20,20,30), (56, 232-leg_off, 32, 10))
shirt = (150, 60, 60)
if mood == "sad": shirt = (110, 50, 50)
R(shirt, (22, 120, 76, 82))
for i in range(5):
R((110, 40, 40), (22, 128+i*14, 76, 3))
pygame.draw.ellipse(surf, shirt,
(x + int(20*s), y + int(158*s), int(80*s), int(70*s)))
pygame.draw.ellipse(surf, (110,40,40),
(x + int(20*s), y + int(158*s), int(80*s), int(70*s)), max(1, int(2*s)))
for i in range(3):
R((240,220,180), (58, 135+i*22, 4, 4))
arm_off = int(math.sin(frame*0.15) * 5) if action == "cook" else 0
R(C_SKIN, (10, 124, 16, 55+arm_off))
R(C_SKIN_D, (10, 174+arm_off, 16, 8))
R(C_SKIN, (94, 124, 16, 55-arm_off))
R(C_SKIN_D, (94, 174-arm_off, 16, 8))
R(shirt, (10, 124, 16, 22))
R(shirt, (94, 124, 16, 22))
R(C_SKIN_D, (48, 105, 24, 18))
pygame.draw.ellipse(surf, C_SKIN,
(x + int(32*s), y + int(30*s), int(56*s), int(82*s)))
pygame.draw.ellipse(surf, C_SKIN_D,
(x + int(32*s), y + int(30*s), int(56*s), int(82*s)), max(1, int(2*s)))
R(C_SKIN, (28, 60, 8, 14))
R(C_SKIN, (84, 60, 8, 14))
beard_col = (55, 40, 30)
pygame.draw.ellipse(surf, beard_col,
(x + int(34*s), y + int(72*s), int(52*s), int(40*s)))
pygame.draw.ellipse(surf, beard_col,
(x + int(40*s), y + int(82*s), int(40*s), int(30*s)))
eye_y = 62
if mood == "happy":
pygame.draw.arc(surf, C_HAIR,
(x + int(40*s), y + int(eye_y*s), int(14*s), int(10*s)),
math.pi, 2*math.pi, max(1, int(3*s)))
pygame.draw.arc(surf, C_HAIR,
(x + int(66*s), y + int(eye_y*s), int(14*s), int(10*s)),
math.pi, 2*math.pi, max(1, int(3*s)))
elif mood == "angry":
R(C_HAIR, (38, eye_y-6, 16, 4))
R(C_HAIR, (66, eye_y-6, 16, 4))
pygame.draw.circle(surf, (255,255,255),
(x + int(46*s), y + int((eye_y+2)*s)), int(6*s))
pygame.draw.circle(surf, (255,255,255),
(x + int(72*s), y + int((eye_y+2)*s)), int(6*s))
pygame.draw.circle(surf, C_HAIR,
(x + int(47*s), y + int((eye_y+2)*s)), int(3*s))
pygame.draw.circle(surf, C_HAIR,
(x + int(73*s), y + int((eye_y+2)*s)), int(3*s))
else:
pygame.draw.circle(surf, (255,255,255),
(x + int(46*s), y + int((eye_y+2)*s)), int(6*s))
pygame.draw.circle(surf, (255,255,255),
(x + int(72*s), y + int((eye_y+2)*s)), int(6*s))
pygame.draw.circle(surf, C_HAIR,
(x + int(47*s), y + int((eye_y+2)*s)), int(3*s))
pygame.draw.circle(surf, C_HAIR,
(x + int(73*s), y + int((eye_y+2)*s)), int(3*s))
pygame.draw.ellipse(surf, C_SKIN_D,
(x + int(56*s), y + int((eye_y+10)*s), int(8*s), int(12*s)))
cap_col = (55, 60, 85)
pygame.draw.arc(surf, cap_col,
(x + int(28*s), y + int(18*s), int(64*s), int(54*s)),
0, math.pi, int(18*s))
R(cap_col, (30, 34, 60, 14))
pygame.draw.ellipse(surf, (40,45,70),
(x + int(20*s), y + int(36*s), int(30*s), int(12*s)))
R((100,90,70), (58, 20, 6, 6))
def draw_customer(surf, x, y, seed, mood="normal", frame=0):
rng = random.Random(seed)
skin = rng.choice([(235,200,170),(210,170,135),(180,140,100),(150,110,75),(120,85,60)])
shirt = rng.choice([(200,80,80),(80,140,200),(180,180,80),(140,80,180),
(200,140,60),(80,180,140),(60,60,120),(230,90,140),
(100,100,100),(200,200,200)])
pants = rng.choice([(40,40,80),(60,50,40),(20,30,60),(80,60,40)])
hair_col = rng.choice([(30,20,15),(80,50,30),(200,180,140),(120,80,50),
(180,80,40),(60,60,60),(230,220,180)])
def R(c, rect):
pygame.draw.rect(surf, c, (x+rect[0], y+rect[1], rect[2], rect[3]))
R(pants, (22, 160, 20, 40))
R(pants, (52, 160, 20, 40))
R((30,30,30), (18, 194, 26, 10))
R((30,30,30), (50, 194, 26, 10))
R(shirt, (18, 96, 58, 66))
arm_sw = int(math.sin(frame*0.08) * 3)
R(skin, (6, 102+arm_sw, 12, 48))
R(skin, (76, 102-arm_sw, 12, 48))
pygame.draw.ellipse(surf, skin, (x+24, y+32, 46, 60))
pygame.draw.ellipse(surf, tuple(max(0,c-30) for c in skin), (x+24, y+32, 46, 60), 2)
R(skin, (20, 58, 8, 12))
R(skin, (66, 58, 8, 12))
style = rng.randint(0, 5)
if style == 0:
pygame.draw.arc(surf, hair_col, (x+22, y+24, 50, 60), 0.1, math.pi-0.1, 10)
R(hair_col, (24, 32, 46, 10))
elif style == 1:
pygame.draw.arc(surf, hair_col, (x+22, y+22, 50, 60), 0.1, math.pi-0.1, 12)
R(hair_col, (22, 32, 50, 24))
elif style == 2:
pygame.draw.arc(surf, hair_col, (x+22, y+30, 50, 60), math.pi, 2*math.pi, 4)
elif style == 3:
pygame.draw.arc(surf, hair_col, (x+22, y+24, 50, 60), 0.1, math.pi-0.1, 10)
R(hair_col, (24, 32, 46, 12))
R(hair_col, (68, 44, 8, 20))
elif style == 4:
R(hair_col, (40, 20, 14, 20))
else:
for i in range(6):
r = 8 + rng.randint(0, 4)
pygame.draw.circle(surf, hair_col, (32+i*7, 34+((i%2)*4)), r)
for dx in [0, 24]:
pygame.draw.circle(surf, (255,255,255), (x+38+dx, y+58), 5)
pygame.draw.circle(surf, (25,25,40), (x+38+dx, y+58), 3)
R(tuple(max(0,c-30) for c in skin), (44, 68, 6, 6))
if mood == "happy":
pygame.draw.arc(surf, (120,50,50), (x+38, y+76, 20, 10), 0, math.pi, 2)
elif mood == "angry":
R((120,50,50), (40, 82, 16, 2))
else:
R((120,50,50), (42, 80, 12, 2))
# ============================== ЧАСТИЦЫ ==============================
class Particle:
def __init__(self, x, y, vx, vy, life, color, size=3, gravity=0.2, glow=False, text=None):
self.x, self.y, self.vx, self.vy = x, y, vx, vy
self.life = self.max_life = life
self.color, self.size, self.gravity, self.glow = color, size, gravity, glow
self.text = text
def update(self):
self.vy += self.gravity
self.x += self.vx
self.y += self.vy
self.life -= 1
class Particles:
def __init__(self):
self.list = []
def emit(self, x, y, n, color, spread=3, life=30, size=3, gravity=0.2, glow=False):
for _ in range(n):
self.list.append(Particle(
x+random.uniform(-4,4), y+random.uniform(-4,4),
random.uniform(-spread,spread), random.uniform(-spread,spread),
random.randint(life//2, life), color, size, gravity, glow))
def text(self, x, y, text, color):
self.list.append(Particle(x, y, 0, -1.5, 60, color, 0, 0.05, False, text))
def update(self):
for p in self.list[:]:
p.update()
if p.life <= 0:
self.list.remove(p)
def draw(self, surf, cam_x=0, cam_y=0):
for p in self.list:
sx, sy = int(p.x - cam_x), int(p.y - cam_y)
if p.text:
a = min(255, p.life * 5)
s = font_m.render(p.text, True, p.color)
s.set_alpha(a)
surf.blit(s, (sx - s.get_width()//2, sy))
continue
a = int(255 * p.life / p.max_life)
if p.glow:
g = pygame.Surface((p.size*6, p.size*6), pygame.SRCALPHA)
pygame.draw.circle(g, (*p.color, a//4), (p.size*3, p.size*3), p.size*3)
surf.blit(g, (sx-p.size*3, sy-p.size*3))
s = pygame.Surface((p.size*2, p.size*2), pygame.SRCALPHA)
pygame.draw.circle(s, (*p.color, a), (p.size, p.size), p.size)
surf.blit(s, (sx-p.size, sy-p.size))
# ============================== ДАННЫЕ ИГРЫ ==============================
class Upgrade:
def __init__(self, id, name, desc, price, cat):
self.id, self.name, self.desc, self.price, self.cat = id, name, desc, price, cat
UPGRADES = [
Upgrade("sign", "Новая вывеска", "Больше клиентов (+15%)", 500, "stall"),
Upgrade("lights", "Гирлянда", "Терпение клиентов +20%", 600, "stall"),
Upgrade("counter", "Широкий прилавок", "Удобнее собирать", 800, "stall"),
Upgrade("menu", "Меню-борд", "Цены +20%", 1000, "stall"),
Upgrade("grill1", "Гриль ур.2", "Мясо готовится быстрее", 900, "kitchen"),
Upgrade("grill2", "Гриль ур.3", "Ещё быстрее, медленнее горит", 2000, "kitchen"),
Upgrade("fridge", "Холодильник", "Все цены +10%", 1200, "kitchen"),
Upgrade("fryer", "Фритюрница", "Открывает картофель фри", 700, "kitchen"),
Upgrade("helper", "Помощник", "Авто-подача готового", 2500, "staff"),
Upgrade("chef", "Повар-напарник", "Авто-готовка мяса", 4000, "staff"),
]
SKILLS = [
{"id":"speed", "name":"Быстрые руки", "desc":"+10% скорость сборки/ур", "max":5, "cost":300},
{"id":"tips", "name":"Душевность", "desc":"+15% к чаевым/ур", "max":5, "cost":300},
{"id":"combo", "name":"Стиль", "desc":"Комбо дольше держится", "max":3, "cost":500},
{"id":"eye", "name":"Зоркий глаз", "desc":"+15% терпения/ур", "max":5, "cost":400},
{"id":"armor", "name":"Стрессоустойч.","desc":"Меньше потери репутации/ур","max":3, "cost":600},
]
def make_order(day, unlocked):
ing = [I_LAVASH]
if I_MEAT_B in unlocked and random.random() < 0.4:
ing.append(I_MEAT_B)
else:
ing.append(I_MEAT_C)
veg = [I_TOMATO, I_CUCUMBER, I_CABBAGE, I_ONION]
n = random.randint(1, min(3, day))
for v in random.sample(veg, n):
ing.append(v)
if I_CHEESE in unlocked and random.random() < 0.4:
ing.append(I_CHEESE)
if I_FRIES in unlocked and random.random() < 0.3:
ing.append(I_FRIES)
sauces = [I_SAUCE_G]
if I_SAUCE_S in unlocked:
sauces.append(I_SAUCE_S)
n_sauce = random.randint(1, min(2, len(sauces)))
for s in random.sample(sauces, n_sauce):
ing.append(s)
ing.append(I_WRAP)
price = 180 + day * 10
for i in ing:
if i == I_MEAT_B: price += 60
elif i == I_CHEESE: price += 40
elif i == I_FRIES: price += 35
elif i == I_SAUCE_S: price += 20
patience = max(20, 40 - day * 1.5)
return ing, price, patience
CUSTOMER_HINTS = ["обычный","голодный","студент","таксист","офисный","постоянный",
"турист","школьник","бабушка","программист","курьер","молодожён"]
# ============================== СУЩНОСТИ РЕАЛЬНОГО ВРЕМЕНИ ==============================
class CustomerRT:
def __init__(self, seed, order_ings, price, patience, hint):
self.seed = seed
self.order = order_ings
self.price = price
self.max_patience = patience
self.patience = patience
self.hint = hint
self.x = W + 60
self.target_x = 980
self.y = 340
self.state = "walk_in"
self.frame = 0
self.mood = "normal"
self.bubble_offset = 0
def update(self, dt):
self.frame += 1
self.bubble_offset = int(math.sin(self.frame * 0.06) * 3)
if self.state == "walk_in":
dx = self.target_x - self.x
if abs(dx) < 4:
self.x = self.target_x
self.state = "waiting"
else:
self.x += math.copysign(min(180 * dt, abs(dx)), dx)
elif self.state == "waiting":
self.patience -= dt
if self.patience <= 0:
self.state = "angry_leave"
self.mood = "angry"
elif self.state == "leaving":
self.x += 260 * dt
if self.x > W + 120:
return "gone"
elif self.state == "angry_leave":
self.x += 400 * dt
if self.x > W + 120:
return "gone_angry"
return None
def draw(self, surf):
draw_customer(surf, int(self.x) - 48, self.y, self.seed, self.mood, self.frame)
if self.state == "waiting":
self._draw_bubble(surf)
def _draw_bubble(self, surf):
bx = int(self.x) - 30
by = self.y - 120 + self.bubble_offset
bw, bh = 240, 70
pygame.draw.rect(surf, (250, 245, 230), (bx, by, bw, bh))
pygame.draw.rect(surf, (60, 50, 40), (bx, by, bw, bh), 2)
pygame.draw.polygon(surf, (250, 245, 230),
[(bx+40, by+bh), (bx+60, by+bh), (bx+50, by+bh+16)])
pygame.draw.line(surf, (60, 50, 40), (bx+40, by+bh), (bx+50, by+bh+16), 2)
pygame.draw.line(surf, (60, 50, 40), (bx+60, by+bh), (bx+50, by+bh+16), 2)
ix, iy = bx + 12, by + 14
for ing in self.order[:9]:
draw_food(surf, ing, ix, iy, 26)
ix += 24
if ix > bx + bw - 30:
ix = bx + 12
iy += 28
ratio = max(0, self.patience / self.max_patience)
bar = pygame.Rect(bx+8, by+bh-8, bw-16, 4)
pygame.draw.rect(surf, (100, 40, 40), bar)
col = C_GREEN if ratio > 0.5 else (C_GOLD if ratio > 0.25 else C_RED)
pygame.draw.rect(surf, col, (bar.x, bar.y, int(bar.w*ratio), bar.h))
class GrillSlot:
def __init__(self):
self.ing = None
self.time = 0.0
self.state = None
def update(self, dt, grill_speed):
if self.ing is None: return
self.time += dt * grill_speed
ct = COOK_TIME.get(self.ing, 4)
bt = BURN_TIME.get(self.ing, 3)
if self.time < ct:
self.state = "raw"
elif self.time < ct + bt:
self.state = "cooked"
else:
self.state = "burned"
def is_empty(self):
return self.ing is None
def place(self, ing):
self.ing = ing
self.time = 0.0
self.state = "raw"
def take(self):
if self.ing is None: return None
r = (self.ing, self.state)
self.ing = None
self.time = 0
return r
# ============================== СОСТОЯНИЕ ==============================
class Game:
def __init__(self):
self.reset()
def reset(self):
self.day = 1
self.money = 500
self.reputation = 50
self.total_earned = 0
self.total_served = 0
self.perfect = 0
self.failed = 0
self.upgrades = set()
self.skills = {}
self.unlocked_ings = {I_LAVASH, I_MEAT_C, I_TOMATO, I_CUCUMBER,
I_CABBAGE, I_ONION, I_CHEESE, I_SAUCE_G, I_WRAP}
self.ending = None
def skill(self, sid):
return self.skills.get(sid, 0)
def has_upg(self, uid):
return uid in self.upgrades
game = Game()
SAVE_FILE = "shawarma_save.json"
def save_game():
data = {
"day": game.day, "money": game.money, "reputation": game.reputation,
"total_earned": game.total_earned, "total_served": game.total_served,
"perfect": game.perfect, "failed": game.failed,
"upgrades": list(game.upgrades), "skills": game.skills,
"unlocked_ings": list(game.unlocked_ings),
}
try:
with open(SAVE_FILE, "w", encoding="utf-8") as f:
json.dump(data, f)
return True
except:
return False
def load_game():
if not os.path.exists(SAVE_FILE): return False
try:
with open(SAVE_FILE, "r", encoding="utf-8") as f:
data = json.load(f)
game.day = data.get("day", 1)
game.money = data.get("money", 500)
game.reputation = data.get("reputation", 50)
game.total_earned = data.get("total_earned", 0)
game.total_served = data.get("total_served", 0)
game.perfect = data.get("perfect", 0)
game.failed = data.get("failed", 0)
game.upgrades = set(data.get("upgrades", []))
game.skills = data.get("skills", {})
game.unlocked_ings = set(data.get("unlocked_ings", list(game.unlocked_ings)))
return True
except:
return False
# ============================== ДИАЛОГИ ==============================
class Dialogue:
def __init__(self, lines):
self.lines = lines
self.i = 0
def cur(self):
return self.lines[self.i] if self.i < len(self.lines) else None
def next(self):
self.i += 1
return self.i < len(self.lines)
def done(self):
return self.i >= len(self.lines)
def wrap(text, font, max_w):
out, cur = [], ""
for w in text.split():
t = (cur + " " + w).strip()
if font.size(t)[0] <= max_w:
cur = t
else:
if cur: out.append(cur)
cur = w
if cur: out.append(cur)
return out
def draw_dialogue(d, frame):
screen.fill(C_NIGHT)
for y in range(H):
k = y / H
pygame.draw.line(screen, (int(20+k*20), int(18+k*18), int(30+k*18)), (0, y), (W, y))
cur = d.cur()
if not cur: return None
speaker = cur.get("speaker")
mood = cur.get("mood", "normal")
if speaker == "kama":
g = pygame.Surface((420, 420), pygame.SRCALPHA)
pygame.draw.circle(g, (255, 200, 100, 40), (210, 210), 200)
screen.blit(g, (40, 100))
draw_kama(screen, 90, 130, 2.4, mood, frame, "cook")
elif speaker == "ogly":
g = pygame.Surface((420, 420), pygame.SRCALPHA)
pygame.draw.circle(g, (255, 200, 100, 40), (210, 210), 200)
screen.blit(g, (40, 100))
draw_ogly(screen, 90, 110, 2.4, mood, frame, "cook")
elif speaker == "customer":
seed = cur.get("seed", 42)
draw_customer(screen, 130, 160, seed, mood, frame)
panel = pygame.Rect(400, H-280, W-440, 240)
pygame.draw.rect(screen, (0,0,0,120), panel.move(6, 6))
pygame.draw.rect(screen, C_PANEL, panel)
pygame.draw.rect(screen, C_GOLD, panel, 3)
names = {"kama":"Камаладдин", "ogly":"Оглы", "customer":"Покупатель",
"narrator":"", "both":"Камаладдин и Оглы", None:""}
name = names.get(speaker, "")
if name:
name_rect = pygame.Rect(panel.x+20, panel.y-34, font_m.size(name)[0]+40, 32)
pygame.draw.rect(screen, C_GOLD_D, name_rect)
pygame.draw.rect(screen, C_GOLD, name_rect, 2)
ns = font_m.render(name, True, C_TEXT)
screen.blit(ns, (name_rect.x+20, name_rect.centery - ns.get_height()//2))
text = cur.get("text", "")
lines = wrap(text, font_l, panel.w - 60)
y = panel.y + 30
for ln in lines[:5]:
ts = font_l.render(ln, True, (20,20,30))
screen.blit(ts, (panel.x+32, y+2))
s = font_l.render(ln, True, C_TEXT)
screen.blit(s, (panel.x+30, y))
y += 32
btn = pygame.Rect(panel.right-220, panel.bottom-56, 200, 42)
pygame.draw.rect(screen, C_PANEL_D, btn)
pygame.draw.rect(screen, C_GOLD, btn, 2)
hint = "Продолжить >>" if not d.done() else "Готово"
hs = font_m.render(hint, True, C_TEXT)
screen.blit(hs, (btn.centerx - hs.get_width()//2, btn.centery - hs.get_height()//2))
ps = font_s.render(f"{d.i+1}/{len(d.lines)} SPACE — далее", True, C_TEXT_DIM)
screen.blit(ps, (panel.x+20, panel.bottom-30))
return btn
def run_dialogue(d):
frame = 0
while not d.done():
clock.tick(60)
frame += 1
draw_dialogue(d, frame)
for e in pygame.event.get():
if e.type == pygame.QUIT:
pygame.quit(); sys.exit()
if e.type == pygame.KEYDOWN and e.key == pygame.K_ESCAPE:
pygame.quit(); sys.exit()
if (e.type == pygame.KEYDOWN and e.key == pygame.K_SPACE) or \
(e.type == pygame.MOUSEBUTTONDOWN and e.button == 1):
d.next()
pygame.display.flip()
# ============================== СЦЕНАРИЙ ==============================
def script_intro():
return Dialogue([
{"speaker":"narrator","text":"Рассвет. Город N. Неоновая вывеска «ШАУРМА №1» мигает и жужжит."},
{"speaker":"ogly","mood":"normal","text":"Камаладдин, сынок! Подъём! Открываемся в семь, а ты дрыхнешь!"},
{"speaker":"kama","mood":"sad","text":"Дядя Оглы, ну пять минут... Я всю ночь изучал рецептуру нового маринада."},
{"speaker":"ogly","mood":"normal","text":"Маринад? У нас один маринад — соль, перец и уважение к клиенту."},
{"speaker":"kama","mood":"happy","text":"Дядя, я хочу открыть свою сеть. Настоящую. С брендом, с логотипом..."},
{"speaker":"ogly","mood":"normal","text":"Мечтатель. Сначала научись не жечь лаваш. Вчера три штуки в мусор ушли."},
{"speaker":"kama","mood":"normal","text":"Это было один раз!"},
{"speaker":"ogly","mood":"happy","text":"Пять, сынок. Я считал. Ладно. Надевай фартук — клиенты идут."},
{"speaker":"narrator","text":"Ты выходишь за прилавок. Сегодня — твой первый настоящий день."},
{"speaker":"narrator","text":"ЦЕЛЬ: 7 дней, репутация >=60, деньги >=1500 — хороший финал."},
])
MORNING_SCRIPTS = {
1: [
{"speaker":"ogly","mood":"normal","text":"Слушай сюда. Клиент называет заказ — ты собираешь."},
{"speaker":"ogly","mood":"normal","text":"Порядок: лаваш, мясо, овощи, соус, завернуть."},
{"speaker":"ogly","mood":"normal","text":"Мясо идёт сначала на гриль. Следи, чтобы не подгорело."},
{"speaker":"narrator","text":"СОВЕТ: кликай ингредиенты внизу. Мясо — в гриль справа. Не зевай."},
],
2: [
{"speaker":"kama","mood":"happy","text":"Дядя, вчера получилось! Три идеальные шаурмы!"},
{"speaker":"ogly","mood":"happy","text":"Молодец. Сегодня пятница — людей будет больше."},
{"speaker":"ogly","mood":"normal","text":"И добавил говядину. Она дороже, но клиенты любят."},
],
3: [
{"speaker":"kama","mood":"normal","text":"Дядя, а почему ты не расширяешься?"},
{"speaker":"ogly","mood":"sad","text":"Был второй ларёк. Сгорел. Газовый баллон, ночь, всё."},
{"speaker":"kama","mood":"surprised","text":"Ого..."},
{"speaker":"ogly","mood":"normal","text":"Вот поэтому у нас всё простое и надёжное."},
],
4: [
{"speaker":"ogly","mood":"sad","text":"Через дорогу открывается «Шаурма Хаус». Сеть."},
{"speaker":"kama","mood":"surprised","text":"Конкуренты?"},
{"speaker":"ogly","mood":"angry","text":"Конкуренты. Цены у них на двадцать рублей ниже."},
{"speaker":"kama","mood":"normal","text":"У нас качество и репутация."},
],
5: [
{"speaker":"kama","mood":"happy","text":"Дядя, идея! «Шаурма дня» — со скидкой, но с сыром."},
{"speaker":"ogly","mood":"happy","text":"Хм. Ладно, чертёнок. Открывай фритюрницу."},
],
6: [
{"speaker":"narrator","text":"Дождь. Улица пустая. Оглы мрачно смотрит на выручку."},
{"speaker":"ogly","mood":"sad","text":"Плохой день. В такую погоду никто не идёт."},
{"speaker":"kama","mood":"happy","text":"А давай доставку? Я разнесу по офисам."},
{"speaker":"ogly","mood":"happy","text":"Мечтатель. Ладно, если выстоим — придумаем."},
],
7: [
{"speaker":"narrator","text":"Последний день. Судьба ларька решится сегодня."},
{"speaker":"ogly","mood":"normal","text":"Камаладдин. Год назад я взял тебя посудомойщиком."},
{"speaker":"kama","mood":"normal","text":"А теперь я делаю шаурму быстрее тебя, дядя."},
{"speaker":"ogly","mood":"happy","text":"Быстрее? Спортивный интерес. Покажи всё, чему научился."},
],
}
EVENING_SCRIPTS = {
1: [
{"speaker":"ogly","mood":"normal","text":"Первый день. Как ощущения?"},
{"speaker":"kama","mood":"normal","text":"Тяжело. Но интересно."},
{"speaker":"ogly","mood":"happy","text":"Это нормально. К вечеру руки привыкнут."},
],
2: [
{"speaker":"ogly","mood":"happy","text":"С говядиной разобрался! Хвалю."},
{"speaker":"kama","mood":"happy","text":"Она дороже, но клиенты довольные уходят."},
],
3: [
{"speaker":"ogly","mood":"sad","text":"Я сегодня вспомнил тот ларёк. Который сгорел."},
{"speaker":"kama","mood":"normal","text":"Дядя, ты его отстроил заново. Здесь."},
{"speaker":"ogly","mood":"normal","text":"Отстроил. Но страх остался."},
],
4: [
{"speaker":"ogly","mood":"angry","text":"Видел их вывеску? Срам какой-то."},
{"speaker":"kama","mood":"normal","text":"Зато у нас — с душой."},
{"speaker":"ogly","mood":"happy","text":"Философ. Но прав. Сегодня не проиграли."},
],
5: [
{"speaker":"kama","mood":"happy","text":"Дядя! «Шаурма дня» улетела за час!"},
{"speaker":"ogly","mood":"happy","text":"Признаю, идея годная. Кто бы мог подумать."},
],
6: [
{"speaker":"ogly","mood":"normal","text":"Доставку завтра сделаем. Я подумал — идея годная."},
{"speaker":"kama","mood":"happy","text":"Правда?!"},
{"speaker":"ogly","mood":"happy","text":"Правда. Но сначала — приложение и логотип."},
],
7: [
{"speaker":"narrator","text":"Конец седьмого дня. Оглы вытирает руки о фартук."},
],
}
def ending_good():
return Dialogue([
{"speaker":"ogly","mood":"happy","text":"Камаладдин. Я 27 лет стою за этим прилавком. И знаешь что?"},
{"speaker":"kama","mood":"normal","text":"Что, дядя?"},
{"speaker":"ogly","mood":"happy","text":"Ты — лучший, кого я видел. И я не про мясо. Я про голову."},
{"speaker":"ogly","mood":"normal","text":"Помнишь, ты говорил про сеть? Я подумал. Надо делать."},
{"speaker":"kama","mood":"surprised","text":"Серьёзно?!"},
{"speaker":"ogly","mood":"happy","text":"Серьёзно. Первый ларёк — здесь. Второй — твой."},
{"speaker":"kama","mood":"happy","text":"Я готов, дядя. Я готов!"},
{"speaker":"ogly","mood":"happy","text":"Название придумал?"},
{"speaker":"kama","mood":"happy","text":"«Камаладдин и Оглы». Чтобы все знали."},
{"speaker":"narrator","text":">>> ХОРОШИЙ ФИНАЛ. Сеть основана."},
])
def ending_neutral():
return Dialogue([
{"speaker":"ogly","mood":"normal","text":"Ну что, Камаладдин. Выстояли."},
{"speaker":"kama","mood":"normal","text":"Выстояли. Но могли лучше."},
{"speaker":"ogly","mood":"normal","text":"Могли. Но и так неплохо."},
{"speaker":"ogly","mood":"happy","text":"Через год — поговорим о расширении."},
{"speaker":"narrator","text":">>> НЕЙТРАЛЬНЫЙ ФИНАЛ."},
])
def ending_bad():
return Dialogue([
{"speaker":"narrator","text":"Молчание. Пустая касса. За окном — конкурент."},
{"speaker":"ogly","mood":"sad","text":"Не тот месяц. Не та неделя. Не тот ты."},
{"speaker":"kama","mood":"sad","text":"Дядя, я старался..."},
{"speaker":"ogly","mood":"sad","text":"Бизнес — не про «старался». Бизнес — про результат."},
{"speaker":"narrator","text":">>> ПЛОХОЙ ФИНАЛ. Ты можешь попробовать снова."},
])
# ============================== МЕНЮ ==============================
class FloatingIng:
def __init__(self):
self.reset()
self.y = random.randint(-400, H)
def reset(self):
self.x = random.randint(0, W)
self.y = -random.randint(40, 400)
self.ing = random.choice(list(ING_NAME.keys()))
self.size = random.randint(38, 58)
self.rot = random.uniform(-15, 15)
self.spin = random.uniform(-0.3, 0.3)
self.vy = random.uniform(0.4, 1.2)
self.vx = random.uniform(-0.3, 0.3)
def draw_menu_bg(frame):
for y in range(H):
k = y / H
pygame.draw.line(screen, (int(12+k*20), int(10+k*16), int(28+k*22)), (0, y), (W, y))
rng = random.Random(123)
for i in range(60):
sx = rng.randint(0, W)
sy = rng.randint(0, 240)
tw = (math.sin(frame*0.05 + i) * 0.5 + 0.5)
c = int(140 + tw * 115)
pygame.draw.circle(screen, (c,c,c), (sx, sy), 1)
rng2 = random.Random(777)
x = -20
while x < W + 40:
bw = rng2.randint(60, 120)
bh = rng2.randint(60, 180)
pygame.draw.rect(screen, (30, 25, 50), (x, 380 - bh, bw, bh))
for wy in range(390 - bh, 370, 20):
for wx in range(x+10, x+bw-10, 18):
lit = rng2.random() < 0.35
c = (245, 200, 100) if lit else (40, 35, 60)
pygame.draw.rect(screen, c, (wx, wy, 8, 12))
x += bw + 8
pygame.draw.rect(screen, (30, 28, 38), (0, 380, W, H-380))
for i in range(0, W, 40):
pygame.draw.line(screen, (45, 42, 55), (i, 380), (i-30, H), 1)
stall_y = 400
pygame.draw.rect(screen, (55, 35, 25), (60, stall_y, 320, 200))
pygame.draw.rect(screen, (80, 50, 35), (60, stall_y, 320, 20))
pygame.draw.rect(screen, (200, 50, 50), (80, stall_y-50, 280, 40))
pygame.draw.rect(screen, (245, 200, 80), (80, stall_y-50, 280, 40), 3)
lit = (frame // 30) % 2 == 0
lbl = font_l.render("ШАУРМА №1", True, (250, 240, 200) if lit else (150, 140, 100))
screen.blit(lbl, (220 - lbl.get_width()//2, stall_y - 40))
def draw_main_menu(floats, frame):
draw_menu_bg(frame)
for f in floats:
if f.y > H + 60:
f.reset()
f.y += f.vy
f.x += f.vx
f.rot += f.spin
for f in floats:
surf = pygame.Surface((f.size + 8, f.size + 8), pygame.SRCALPHA)
draw_food(surf, f.ing, 4, 4, f.size)
surf.set_alpha(140)
rotated = pygame.transform.rotate(surf, f.rot)
rect = rotated.get_rect(center=(f.x, f.y))
screen.blit(rotated, rect)
overlay = pygame.Surface((W, H), pygame.SRCALPHA)
pygame.draw.rect(overlay, (10, 8, 18, 140), (0, 0, W, H))
screen.blit(overlay, (0, 0))
title_shadow = font_xxl.render("ШАУРМИСТ", True, (10, 8, 20))
title = font_xxl.render("ШАУРМИСТ", True, C_GOLD)
tx = W//2 - title.get_width()//2
ty = 80 + int(math.sin(frame*0.03) * 4)
screen.blit(title_shadow, (tx+4, ty+4))
screen.blit(title, (tx, ty))
subtitle = font_l.render("Камаладдин и Оглы", True, C_TEXT)
screen.blit(subtitle, (W//2 - subtitle.get_width()//2, ty + title.get_height() - 6))
draw_kama(screen, 180, 300, 1.6, "happy", frame, "walk")
draw_ogly(screen, 950, 280, 1.6, "happy", frame, "cook")
buttons = [
("НОВАЯ ИГРА", "new"),
("ПРОДОЛЖИТЬ", "continue"),
("ОБ ИГРЕ", "about"),
("ВЫХОД", "exit"),
]
rects = []
bx = W//2 - 160
by = 320
for text, key in buttons:
r = pygame.Rect(bx, by, 320, 52)
rects.append((r, key, text))
by += 62
mx, my = pygame.mouse.get_pos()
for r, key, text in rects:
hover = r.collidepoint(mx, my)
pygame.draw.rect(screen, (10,10,20), r.move(4, 4))
bg_col = (80, 60, 100) if hover else C_PANEL
if key == "continue" and not os.path.exists(SAVE_FILE):
bg_col = (40, 40, 45)
pygame.draw.rect(screen, bg_col, r)
pygame.draw.rect(screen, C_GOLD if hover else C_GOLD_D, r, 3 if hover else 2)
tc = C_TEXT
if key == "continue" and not os.path.exists(SAVE_FILE):
tc = C_TEXT_DIM
s = font_l.render(text, True, tc)
screen.blit(s, (r.centerx - s.get_width()//2, r.centery - s.get_height()//2))
info = font_s.render("v1.1 © 2025 Made with pygame", True, C_TEXT_DIM)
screen.blit(info, (W//2 - info.get_width()//2, H-30))
return rects
def about_screen():
frame = 0
while True:
clock.tick(60)
frame += 1
for e in pygame.event.get():
if e.type == pygame.QUIT:
pygame.quit(); sys.exit()
if e.type == pygame.KEYDOWN or e.type == pygame.MOUSEBUTTONDOWN:
return
screen.fill(C_NIGHT)
for y in range(H):
k = y/H
pygame.draw.line(screen, (int(20+k*20), int(18+k*16), int(30+k*22)), (0,y), (W,y))
title = font_xl.render("ОБ ИГРЕ", True, C_GOLD)
screen.blit(title, (W//2 - title.get_width()//2, 40))
lines = [
"СИМУЛЯТОР ШАУРМИСТА — история двух друзей.",
"",
"Камаладдин — молодой, амбициозный, мечтает о сети.",
"Оглы — его старший друг, владелец ларька.",
"",
"УПРАВЛЕНИЕ:",
" МЫШЬ — выбирать ингредиенты и кнопки",
" SPACE — диалоги / отказать клиенту",
" ESC — закрыть меню",
"",
"МЕХАНИКА:",
" • Клиенты приходят в реальном времени",
" • Собирай: лаваш → мясо → овощи → соус → завернуть",
" • Мясо готовится на гриле — не дай подгореть!",
" • Апгрейды ларька и навыки открывают новое",
"",
"ЦЕЛЬ: 7 дней, репутация >=60, деньги >=1500.",
"",
"SPACE / клик — назад",
]
y = 130
for line in lines:
s = font_m.render(line, True, C_TEXT if not line.startswith(" ") else C_TEXT_DIM)
screen.blit(s, (W//2 - s.get_width()//2, y))
y += 26
pygame.display.flip()
# ============================== МАГАЗИН ==============================
def shop_screen():
frame = 0
scroll = 0
mx, my = 0, 0
while True:
clock.tick(60)
frame += 1
mx, my = pygame.mouse.get_pos()
for e in pygame.event.get():
if e.type == pygame.QUIT:
pygame.quit(); sys.exit()
if e.type == pygame.KEYDOWN and e.key == pygame.K_ESCAPE:
return
if e.type == pygame.MOUSEBUTTONDOWN:
if e.button == 4:
scroll = min(0, scroll + 20)
if e.button == 5:
scroll -= 20
if e.button == 1:
for i, up in enumerate(UPGRADES):
y = 130 + i*90 + scroll
r = pygame.Rect(60, y, W-200, 80)
if r.collidepoint(mx, my):
if up.id not in game.upgrades and game.money >= up.price:
game.money -= up.price
game.upgrades.add(up.id)
if up.id == "fryer":
game.unlocked_ings.add(I_FRIES)
screen.fill(C_BG)
pygame.draw.rect(screen, C_PANEL, (0, 0, W, 100))
t = font_xl.render("МАГАЗИН ЛАРЬКА", True, C_GOLD)
screen.blit(t, (W//2 - t.get_width()//2, 20))
m = font_l.render(f"{game.money}₽", True, C_GREEN)
screen.blit(m, (W - m.get_width() - 30, 40))
cats = {"stall": "ЛАРЁК", "kitchen": "КУХНЯ", "staff": "ПЕРСОНАЛ"}
cat_col = {"stall": C_GOLD, "kitchen": C_ORANGE, "staff": C_PURPLE}
cur_cat = None
for i, up in enumerate(UPGRADES):
y = 130 + i*90 + scroll
if y < -100 or y > H:
continue
if up.cat != cur_cat:
cur_cat = up.cat
label = font_m.render(cats.get(up.cat, "?"), True, cat_col[up.cat])
screen.blit(label, (60, y - 24))
r = pygame.Rect(60, y, W-200, 80)
hover = r.collidepoint(mx, my)
bought = up.id in game.upgrades
can = game.money >= up.price and not bought
bg = (55, 85, 55) if bought else ((70, 60, 100) if can and hover else C_PANEL_D)
pygame.draw.rect(screen, bg, r)
border = C_GREEN_D if bought else (C_GOLD if can else C_TEXT_DIM)
pygame.draw.rect(screen, border, r, 2)
ns = font_m.render(up.name, True, C_TEXT)
screen.blit(ns, (r.x+20, r.y+8))
ds = font_s.render(up.desc, True, C_TEXT_DIM)
screen.blit(ds, (r.x+20, r.y+36))
pr_txt = "КУПЛЕНО" if bought else f"{up.price}₽"
pr_col = C_GREEN if bought or can else C_RED
ps = font_m.render(pr_txt, True, pr_col)
screen.blit(ps, (r.right - ps.get_width() - 20, r.centery - ps.get_height()//2))
hint = font_s.render("ESC — закрыть", True, C_TEXT_DIM)
screen.blit(hint, (30, H-30))
pygame.display.flip()
# ============================== НАВЫКИ ==============================
def skills_screen():
frame = 0
mx, my = 0, 0
while True:
clock.tick(60)
frame += 1
mx, my = pygame.mouse.get_pos()
for e in pygame.event.get():
if e.type == pygame.QUIT:
pygame.quit(); sys.exit()
if e.type == pygame.KEYDOWN and e.key == pygame.K_ESCAPE:
return
if e.type == pygame.MOUSEBUTTONDOWN and e.button == 1:
for i, sk in enumerate(SKILLS):
r = pygame.Rect(60, 130 + i*90, W-120, 80)
if r.collidepoint(mx, my):
lvl = game.skill(sk["id"])
cost = sk["cost"] * (lvl + 1)
if lvl < sk["max"] and game.money >= cost:
game.money -= cost
game.skills[sk["id"]] = lvl + 1
screen.fill(C_BG)
pygame.draw.rect(screen, C_PANEL, (0, 0, W, 100))
t = font_xl.render("НАВЫКИ КАМАЛАДДИНА", True, C_PURPLE)
screen.blit(t, (W//2 - t.get_width()//2, 20))
m = font_l.render(f"{game.money}₽", True, C_GREEN)
screen.blit(m, (W - m.get_width() - 30, 40))
for i, sk in enumerate(SKILLS):
r = pygame.Rect(60, 130 + i*90, W-120, 80)
lvl = game.skill(sk["id"])
maxed = lvl >= sk["max"]
cost = sk["cost"] * (lvl + 1)
can = not maxed and game.money >= cost
hover = r.collidepoint(mx, my)
bg = (70, 55, 90) if hover and can else C_PANEL_D
pygame.draw.rect(screen, bg, r)
border = C_PURPLE if can else C_TEXT_DIM
if maxed:
border = C_GREEN_D
pygame.draw.rect(screen, border, r, 2)
ns = font_m.render(sk["name"], True, C_TEXT)
screen.blit(ns, (r.x+20, r.y+8))
ds = font_s.render(sk["desc"], True, C_TEXT_DIM)
screen.blit(ds, (r.x+20, r.y+38))
for j in range(sk["max"]):
rx = r.x + 500 + j*24
ry = r.centery - 10
filled = j < lvl
pygame.draw.rect(screen, C_GREEN if filled else C_PANEL, (rx, ry, 18, 18))
pygame.draw.rect(screen, C_TEXT_DIM, (rx, ry, 18, 18), 2)
if maxed:
pr = "МАКС"
col = C_GREEN_D
else:
pr = f"{cost}₽"
col = C_GREEN if can else C_RED
ps = font_m.render(pr, True, col)
screen.blit(ps, (r.right - ps.get_width() - 20, r.centery - ps.get_height()//2))
hint = font_s.render("ESC — закрыть", True, C_TEXT_DIM)
screen.blit(hint, (30, H-30))
pygame.display.flip()
# ============================== ИТОГ ДНЯ ==============================
def day_summary(day, earned, served, perfect, failed):
btn = pygame.Rect(W//2-180, H-110, 360, 60)
frame = 0
while True:
clock.tick(60)
frame += 1
mx, my = pygame.mouse.get_pos()
for e in pygame.event.get():
if e.type == pygame.QUIT:
pygame.quit(); sys.exit()
if e.type == pygame.KEYDOWN and e.key == pygame.K_SPACE:
return
if e.type == pygame.MOUSEBUTTONDOWN and e.button == 1 and btn.collidepoint(mx, my):
return
screen.fill(C_NIGHT)
for y in range(H):
k = y/H
pygame.draw.line(screen, (int(20+k*22), int(18+k*20), int(30+k*26)), (0,y), (W,y))
t = font_xxl.render(f"КОНЕЦ ДНЯ {day}", True, C_GOLD)
screen.blit(t, (W//2 - t.get_width()//2, 60))
panel = pygame.Rect(W//2-400, 200, 800, 380)
pygame.draw.rect(screen, C_PANEL, panel)
pygame.draw.rect(screen, C_GOLD, panel, 3)
rows = [
("Обслужено клиентов", f"{served}", C_TEXT),
("Идеальных заказов", f"{perfect}", C_GREEN),
("Провалено", f"{failed}", C_RED),
("Заработано за день", f"{earned}₽", C_GOLD),
("Всего в кассе", f"{game.money}₽", C_GREEN),
("Репутация", f"{game.reputation}", C_BLUE),
]
y = panel.y + 30
for label, value, col in rows:
ls = font_l.render(label, True, C_TEXT_DIM)
screen.blit(ls, (panel.x+40, y))
vs = font_l.render(value, True, col)
screen.blit(vs, (panel.right - vs.get_width() - 40, y))
y += 52
hover = btn.collidepoint(mx, my)
pygame.draw.rect(screen, (90,70,120) if hover else C_PANEL, btn)
pygame.draw.rect(screen, C_GOLD, btn, 3)
bs = font_l.render("ПРОДОЛЖИТЬ >>", True, C_TEXT)
screen.blit(bs, (btn.centerx - bs.get_width()//2, btn.centery - bs.get_height()//2))
pygame.display.flip()
# ============================== ГЕЙМПЛЕЙ ДНЯ ==============================
def play_day(day):
particles = Particles()
base_goal = 6 + day
total_customers = base_goal + random.randint(-1, 2)
if game.has_upg("sign"):
total_customers = int(total_customers * 1.15)
patience_mult = 1.0
if game.has_upg("lights"):
patience_mult += 0.2
patience_mult += game.skill("eye") * 0.15
base_interval = max(3.0, 7.0 - day * 0.4)
if game.has_upg("sign"):
base_interval *= 0.85
price_mult = 1.0
if game.has_upg("menu"):
price_mult += 0.2
if game.has_upg("fridge"):
price_mult += 0.1
price_mult += game.skill("tips") * 0.05
grill_speed = 1.0
if game.has_upg("grill1"):
grill_speed += 0.3
if game.has_upg("grill2"):
grill_speed += 0.3
scene = pygame.Surface((W, H))
customers = []
next_customer_in = 1.5
queue_served = 0
queue_failed = 0
queue_perfect = 0
earned = 0
current_order_ings = []
grill_slots = [GrillSlot() for _ in range(3)]
all_ings = [I_LAVASH, I_MEAT_C, I_MEAT_B, I_TOMATO, I_CUCUMBER,
I_CABBAGE, I_ONION, I_CHEESE, I_FRIES,
I_SAUCE_G, I_SAUCE_S, I_WRAP]
ing_available = [i for i in all_ings if i in game.unlocked_ings]
ing_available = list(dict.fromkeys(ing_available))
ING_SIZE = 76
ING_GAP = 8
ING_Y = H - 100
ing_rects = []
for i, ing in enumerate(ing_available):
x = 20 + i * (ING_SIZE + ING_GAP)
r = pygame.Rect(x, ING_Y, ING_SIZE, ING_SIZE)
ing_rects.append((r, ing))
GRILL_RECTS = []
grill_x = W - 240
grill_y = 100
for i in range(3):
r = pygame.Rect(grill_x, grill_y + i*110, 200, 100)
GRILL_RECTS.append(r)
msg = ""
msg_t = 0
msg_col = C_TEXT
last_t = pygame.time.get_ticks()
frame = 0
day_ending = False
end_t = 0.0
while not day_ending:
now = pygame.time.get_ticks()
dt = min(0.05, (now - last_t) / 1000.0)
last_t = now
frame += 1
clock.tick(60)
next_customer_in -= dt
if next_customer_in <= 0 and len(customers) < 4:
next_customer_in = base_interval * random.uniform(0.7, 1.4)
seed = random.randint(0, 10**6)
order_ings, base_price, base_pat = make_order(day, game.unlocked_ings)
final_price = int(base_price * price_mult)
final_pat = base_pat * patience_mult
hint = random.choice(CUSTOMER_HINTS)
customers.append(CustomerRT(seed, order_ings, final_price, final_pat, hint))
for c in customers[:]:
res = c.update(dt)
if res == "gone":
customers.remove(c)
elif res == "gone_angry":
customers.remove(c)
queue_failed += 1
game.reputation = max(0, game.reputation - 3 + game.skill("armor"))
msg = "Клиент ушёл! Репутация -3"
msg_col = C_RED
msg_t = 120
particles.emit(c.x, c.y+30, 12, (200,60,60), 4, 30, 3)
for g in grill_slots:
g.update(dt, grill_speed)
if game.has_upg("chef") and g.is_empty():
for c in customers:
if c.state != "waiting":
continue
if I_MEAT_C in c.order or I_MEAT_B in c.order:
meat = I_MEAT_B if I_MEAT_B in c.order else I_MEAT_C
g.place(meat)
break
mx, my = pygame.mouse.get_pos()
left_click = False
for e in pygame.event.get():
if e.type == pygame.QUIT:
pygame.quit(); sys.exit()
if e.type == pygame.KEYDOWN:
if e.key == pygame.K_ESCAPE:
pygame.quit(); sys.exit()
if e.key == pygame.K_SPACE:
waiting = [c for c in customers if c.state == "waiting"]
if waiting:
c = waiting[0]
customers.remove(c)
queue_failed += 1
game.reputation = max(0, game.reputation - 2 + game.skill("armor"))
msg = "Отказал клиенту. Репутация -2"
msg_col = C_RED
msg_t = 120
if e.type == pygame.MOUSEBUTTONDOWN and e.button == 1:
left_click = True
if left_click:
for r, ing in ing_rects:
if r.collidepoint(mx, my):
waiting = [c for c in customers if c.state == "waiting"]
if not waiting:
msg = "Нет клиента — некому отдать"
msg_col = C_TEXT_DIM
msg_t = 90
break
c = waiting[0]
expected_pos = len(current_order_ings)
if expected_pos >= len(c.order):
msg = "Заказ собран, отдай!"
msg_col = C_TEXT_DIM
msg_t = 90
break
expected = c.order[expected_pos]
if ing in GRILL_INGS:
if expected != ing:
msg = f"Сейчас нужно: {ING_SHORT[expected]}"
msg_col = C_RED
msg_t = 90
break
placed = False
for gi, g in enumerate(grill_slots):
if g.is_empty():
g.place(ing)
placed = True
particles.emit(r.centerx, r.centery, 6, (240,200,120), 2, 20)
break
if not placed:
msg = "Гриль занят!"
msg_col = C_RED
msg_t = 90
break
if ing == expected:
current_order_ings.append(ing)
particles.emit(r.centerx, r.centery, 5, (240,240,200), 2, 20)
if ing == I_WRAP:
c.state = "leaving"
c.mood = "happy"
ratio = c.patience / c.max_patience
quality = "perfect" if ratio > 0.4 else "good"
if quality == "perfect":
earn = int(c.price * 1.35)
queue_perfect += 1
game.reputation = min(100, game.reputation + 3)
particles.text(c.x, c.y-60, "PERFECT!", C_GOLD)
msg = f"PERFECT! +{earn}₽"
msg_col = C_GOLD
game.perfect += 1
else:
earn = int(c.price * 1.1)
game.reputation = min(100, game.reputation + 2)
particles.text(c.x, c.y-60, "ХОРОШО", C_GREEN)
msg = f"+{earn}₽"
msg_col = C_GREEN
msg_t = 120
earned += earn
queue_served += 1
game.total_served += 1
current_order_ings = []
particles.emit(c.x, c.y, 15, C_GOLD, 4, 30, 3, glow=True)
break
else:
msg = f"Не то. Нужно: {ING_SHORT[expected]}"
msg_col = C_RED
msg_t = 90
break
for gi, r in enumerate(GRILL_RECTS):
if r.collidepoint(mx, my):
g = grill_slots[gi]
if g.is_empty():
break
if g.state == "burned":
g.take()
msg = "Сгорело! Выкинул."
msg_col = C_RED
msg_t = 90
particles.emit(r.centerx, r.centery, 8, (60,40,30), 3, 25)
break
if g.state == "raw":
msg = "Ещё сырое!"
msg_col = C_GOLD
msg_t = 90
break
waiting = [c for c in customers if c.state == "waiting"]
if not waiting:
msg = "Некому отдать"
msg_col = C_TEXT_DIM
msg_t = 90
break
c = waiting[0]
expected_pos = len(current_order_ings)
if expected_pos >= len(c.order):
break
expected = c.order[expected_pos]
if expected == g.ing:
current_order_ings.append(g.ing)
g.take()
particles.emit(r.centerx, r.centery, 8, (240,200,120), 3, 25, 2, 0.1)
else:
msg = f"Нужно: {ING_SHORT[expected]}"
msg_col = C_RED
msg_t = 90
break
# ============ РЕНДЕР ============
scene.fill((0,0,0))
for y in range(340):
k = y/340
r = int(60 * (1-k) + 200 * k)
g = int(90 * (1-k) + 160 * k)
b = int(140 * (1-k) + 120 * k)
pygame.draw.line(scene, (r,g,b), (0, y), (W, y))
rng = random.Random(555)
bx = 0
while bx < W:
bw = rng.randint(60, 130)
bh = rng.randint(90, 180)
pygame.draw.rect(scene, (55, 45, 70), (bx, 340-bh, bw, bh))
for wy in range(360 - bh, 330, 22):
for wx in range(bx+10, bx+bw-10, 20):
c = (240, 200, 120) if rng.random() < 0.3 else (40, 35, 55)
pygame.draw.rect(scene, c, (wx, wy, 10, 14))
bx += bw + 6
pygame.draw.rect(scene, (40, 38, 48), (0, 340, W, 120))
for i in range(0, W, 50):
pygame.draw.line(scene, (55, 50, 65), (i, 340), (i, 460), 1)
stall_x = W//2 - 300
stall_y = 240
stall_w = 600
stall_h = 240
pygame.draw.rect(scene, (20, 18, 30), (stall_x-8, stall_y+8, stall_w+16, stall_h))
pygame.draw.rect(scene, (85, 55, 40), (stall_x, stall_y, stall_w, stall_h))
pygame.draw.rect(scene, (60, 40, 30), (stall_x, stall_y, stall_w, 20))
pygame.draw.polygon(scene, (130, 45, 45), [
(stall_x-20, stall_y+10),
(stall_x + stall_w + 20, stall_y+10),
(stall_x + stall_w - 10, stall_y - 30),
(stall_x + 10, stall_y - 30)])
pygame.draw.polygon(scene, (80, 25, 25), [
(stall_x-20, stall_y+10),
(stall_x + stall_w + 20, stall_y+10),
(stall_x + stall_w - 10, stall_y - 30),
(stall_x + 10, stall_y - 30)], 3)
sign_rect = pygame.Rect(stall_x + 140, stall_y - 80, 320, 60)
pygame.draw.rect(scene, (200, 50, 50), sign_rect)
pygame.draw.rect(scene, (245, 200, 80), sign_rect, 4)
lit = (frame // 20) % 2 == 0
sign_text = font_l.render("ШАУРМА", True, (250, 240, 200) if lit else (150, 140, 100))
scene.blit(sign_text, (sign_rect.centerx - sign_text.get_width()//2,
sign_rect.centery - sign_text.get_height()//2))
counter = pygame.Rect(stall_x + 20, stall_y + 130, stall_w - 40, 40)
pygame.draw.rect(scene, (130, 90, 60), counter)
pygame.draw.rect(scene, (90, 60, 40), counter, 3)
menu_board = pygame.Rect(stall_x + 60, stall_y + 30, 200, 100)
pygame.draw.rect(scene, (30, 25, 40), menu_board)
pygame.draw.rect(scene, (200, 180, 120), menu_board, 2)
mb_text = font_s.render("МЕНЮ", True, (240, 220, 160))
scene.blit(mb_text, (menu_board.centerx - mb_text.get_width()//2, menu_board.y + 6))
for i, item in enumerate(["Шаурма", "С сыром", "С фри", "Острая"]):
it = font_xs.render(f"- {item}", True, (220, 210, 180))
scene.blit(it, (menu_board.x + 10, menu_board.y + 30 + i*16))
draw_kama(scene, stall_x + 280, stall_y + 20, 1.6, "normal", frame, "cook")
grill_panel = pygame.Rect(stall_x + 320, stall_y + 60, 240, 100)
pygame.draw.rect(scene, (40, 40, 45), grill_panel)
pygame.draw.rect(scene, (100, 100, 100), grill_panel, 3)
for i in range(3):
pygame.draw.line(scene, (150, 150, 150),
(grill_panel.x, grill_panel.y + 20 + i*25),
(grill_panel.right, grill_panel.y + 20 + i*25), 2)
for i in range(5):
fx = grill_panel.x + 30 + i*45
fy = grill_panel.y + 70 + int(math.sin(frame*0.15 + i) * 4)
col = (240, 120, 40) if frame % 10 < 6 else (250, 180, 60)
pygame.draw.circle(scene, col, (fx, fy), 4)
pygame.draw.circle(scene, (250, 200, 100), (fx, fy), 2)
screen.blit(scene, (0, 0))
for c in customers:
c.draw(screen)
for i, r in enumerate(GRILL_RECTS):
g = grill_slots[i]
bg = (50, 45, 60) if g.is_empty() else (70, 50, 40)
pygame.draw.rect(screen, bg, r)
pygame.draw.rect(screen, C_PANEL_L, r, 2)
gt = font_s.render(f"ГРИЛЬ #{i+1}", True, C_TEXT_DIM)
screen.blit(gt, (r.x+8, r.y+6))
if g.is_empty():
pt = font_s.render("- пусто -", True, C_TEXT_DIM)
screen.blit(pt, (r.centerx - pt.get_width()//2, r.centery - pt.get_height()//2))
else:
draw_food(screen, g.ing, r.x + 10, r.y + 20, 50, g.state)
ct = COOK_TIME.get(g.ing, 4)
bt = BURN_TIME.get(g.ing, 3)
total = ct + bt
bar = pygame.Rect(r.x + 70, r.y + 30, 120, 14)
pygame.draw.rect(screen, (30,30,30), bar)
if g.state == "raw":
pygame.draw.rect(screen, C_GOLD,
(bar.x, bar.y, int(bar.w * min(1, g.time/ct)), bar.h))
elif g.state == "cooked":
pygame.draw.rect(screen, C_GREEN, bar)
else:
pygame.draw.rect(screen, C_RED, bar)
pygame.draw.rect(screen, C_TEXT_DIM, bar, 2)
st_txt = {"raw":"Сырое", "cooked":"Готово!", "burned":"СГОРЕЛО"}[g.state]
st_col = {"raw":C_GOLD, "cooked":C_GREEN, "burned":C_RED}[g.state]
ss = font_s.render(st_txt, True, st_col)
screen.blit(ss, (r.x+70, r.y+50))
if g.state == "cooked":
hint = font_xs.render("Клик — забрать", True, C_GREEN)
screen.blit(hint, (r.x+70, r.y+70))
for r, ing in ing_rects:
hover = r.collidepoint(mx, my)
bg = (80, 65, 100) if hover else C_PANEL_D
pygame.draw.rect(screen, bg, r)
pygame.draw.rect(screen, C_GOLD if hover else C_TEXT_DIM, r, 2)
draw_food(screen, ing, r.x+6, r.y+2, 60)
nm = font_s.render(ING_SHORT[ing], True, C_TEXT)
screen.blit(nm, (r.centerx - nm.get_width()//2, r.bottom - 18))
top = pygame.Rect(0, 0, W, 40)
pygame.draw.rect(screen, C_PANEL, top)
day_s = font_m.render(f"ДЕНЬ {day}", True, C_GOLD)
screen.blit(day_s, (20, 8))
money_s = font_m.render(f"{game.money + earned}₽", True, C_GREEN)
screen.blit(money_s, (150, 8))
rep_s = font_m.render(f"Репутация: {game.reputation}", True, C_BLUE)
screen.blit(rep_s, (300, 8))
prog_s = font_m.render(
f"Обслужено: {queue_served}/{total_customers} Идеально: {queue_perfect} Провалено: {queue_failed}",
True, C_TEXT)
screen.blit(prog_s, (520, 8))
waiting = [c for c in customers if c.state == "waiting"]
if waiting:
c = waiting[0]
nxt = c.order[len(current_order_ings)] if len(current_order_ings) < len(c.order) else None
hint_rect = pygame.Rect(W//2 - 260, H - 170, 520, 56)
pygame.draw.rect(screen, C_PANEL, hint_rect)
pygame.draw.rect(screen, C_GOLD, hint_rect, 2)
if nxt is not None:
nm = ING_SHORT[nxt]
ht = font_m.render(f"СЛЕДУЮЩИЙ: {nm}", True, C_GOLD)
else:
ht = font_m.render("ВСЁ ГОТОВО — отдать клиенту!", True, C_GREEN)
screen.blit(ht, (hint_rect.centerx - ht.get_width()//2,
hint_rect.centery - ht.get_height()//2))
if msg_t > 0:
msg_t -= 1
ms = font_m.render(msg, True, msg_col)
msh = font_m.render(msg, True, (10,8,20))
screen.blit(msh, (W//2 - ms.get_width()//2 + 2, 62))
screen.blit(ms, (W//2 - ms.get_width()//2, 60))
particles.update()
particles.draw(screen)
if (queue_served + queue_failed >= total_customers) and len(customers) == 0:
if not day_ending:
day_ending = True
end_t = 1.5
if day_ending:
end_t -= dt
if end_t <= 0:
return earned, queue_served, queue_perfect, queue_failed
pygame.display.flip()
return earned, queue_served, queue_perfect, queue_failed
# ============================== ЗАПУСК ==============================
def run_week(start_day):
for day in range(start_day, 8):
if day in MORNING_SCRIPTS:
run_dialogue(Dialogue(MORNING_SCRIPTS[day]))
earned, served, perfect, failed = play_day(day)
game.money += earned
game.total_earned += earned
game.failed += failed
game.day = day + 1
day_summary(day, earned, served, perfect, failed)
if day < 7:
if day in EVENING_SCRIPTS:
run_dialogue(Dialogue(EVENING_SCRIPTS[day]))
shop_screen()
skills_screen()
save_game()
if game.reputation >= 60 and game.money >= 1500:
run_dialogue(ending_good())
game.ending = "good"
elif game.reputation >= 30 or game.money >= 800:
run_dialogue(ending_neutral())
game.ending = "neutral"
else:
run_dialogue(ending_bad())
game.ending = "bad"
def main():
floats = [FloatingIng() for _ in range(18)]
frame = 0
while True:
clock.tick(60)
frame += 1
rects = draw_main_menu(floats, frame)
pygame.display.flip()
mx, my = pygame.mouse.get_pos()
for e in pygame.event.get():
if e.type == pygame.QUIT:
pygame.quit(); sys.exit()
if e.type == pygame.MOUSEBUTTONDOWN and e.button == 1:
for r, key, text in rects:
if r.collidepoint(mx, my):
if key == "new":
game.reset()
run_dialogue(script_intro())
run_week(1)
elif key == "continue":
if load_game():
run_week(game.day)
elif key == "about":
about_screen()
elif key == "exit":
pygame.quit(); sys.exit()
if __name__ == "__main__":
try:
main()
except Exception:
import traceback
traceback.print_exc()
finally:
pygame.quit()