127 lines
4.6 KiB
Python
127 lines
4.6 KiB
Python
import random
|
||
import sqlite3
|
||
import logging
|
||
|
||
import config
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
# Символы слотов и их веса (чем выше вес — тем чаще выпадает)
|
||
SLOT_SYMBOLS = ["🍒", "🍋", "🔔", "💎", "7️⃣", "🍀"]
|
||
SLOT_WEIGHTS = [30, 25, 20, 12, 8, 5] # 🍒 чаще всего, 🍀 реже всего
|
||
|
||
# Множители для выигрышей: {кол-во совпадений: (мин, макс)}
|
||
MULTIPLIERS = {
|
||
2: (1.2, 1.8), # две одинаковых
|
||
3: (2.0, 3.0), # три одинаковых (джекпот, редко)
|
||
}
|
||
|
||
CASINO_WIN_CHANCE = 0.35
|
||
|
||
|
||
def spin_slots() -> tuple[list[str], int]:
|
||
reels = random.choices(SLOT_SYMBOLS, weights=SLOT_WEIGHTS, k=3)
|
||
|
||
if random.random() > CASINO_WIN_CHANCE:
|
||
while len(set(reels)) < 3:
|
||
reels = random.choices(SLOT_SYMBOLS, weights=SLOT_WEIGHTS, k=3)
|
||
return reels, 0
|
||
|
||
counts = {}
|
||
for s in reels:
|
||
counts[s] = counts.get(s, 0) + 1
|
||
max_match = max(counts.values())
|
||
return reels, max_match
|
||
|
||
|
||
def get_user_length(user_id: int) -> float | None:
|
||
try:
|
||
with sqlite3.connect(config.PENIS_DB_PATH) as conn:
|
||
row = conn.execute(
|
||
"SELECT length FROM penis_stats WHERE user_id = ?",
|
||
(user_id,),
|
||
).fetchone()
|
||
return float(row[0]) if row else None
|
||
except sqlite3.Error:
|
||
logger.exception("casino: failed to get length")
|
||
return None
|
||
|
||
|
||
def update_user_length(user_id: int, delta: float) -> float | None:
|
||
try:
|
||
with sqlite3.connect(config.PENIS_DB_PATH) as conn:
|
||
row = conn.execute(
|
||
"SELECT length FROM penis_stats WHERE user_id = ?",
|
||
(user_id,),
|
||
).fetchone()
|
||
if row is None:
|
||
return None
|
||
new_length = round(float(row[0]) + delta, 1)
|
||
conn.execute(
|
||
"UPDATE penis_stats SET length = ? WHERE user_id = ?",
|
||
(new_length, user_id),
|
||
)
|
||
conn.commit()
|
||
return new_length
|
||
except sqlite3.Error:
|
||
logger.exception("casino: failed to update length")
|
||
return None
|
||
|
||
|
||
def play_casino(user_id: int, bet: float) -> str:
|
||
current = get_user_length(user_id)
|
||
if current is None:
|
||
return "Ты ещё ни разу не крутил /penis, братуха. Сначала заведи счёт."
|
||
|
||
# Проверяем отрицательный баланс
|
||
if current <= 0:
|
||
return "🚫 С кредитом в казино не впускают, братуха. Иди наращивай через /penis."
|
||
|
||
# Проверяем максимум ставки
|
||
if bet > config.CASINO_MAX_BET:
|
||
return f"Максимальная ставка — {config.CASINO_MAX_BET} см, не жадничай."
|
||
|
||
if bet <= 0:
|
||
return "Ставка должна быть больше нуля, фраер."
|
||
|
||
# Проверяем хватает ли
|
||
if bet > current:
|
||
return f"У тебя {current:.1f} см, а ставишь {bet:.1f}. Столько нет, фраер."
|
||
|
||
# Крутим
|
||
reels, matches = spin_slots()
|
||
slots_display = " | ".join(reels)
|
||
|
||
if matches >= 2:
|
||
min_mult, max_mult = MULTIPLIERS[matches]
|
||
multiplier = round(random.uniform(min_mult, max_mult), 1)
|
||
winnings = round(bet * multiplier, 1)
|
||
new_length = update_user_length(user_id, winnings)
|
||
if new_length is None:
|
||
return "Ошибка БД. Попробуй позже."
|
||
|
||
if matches == 3:
|
||
return (
|
||
f"🎰 {slots_display}\n\n"
|
||
f"🎉 ДЖЕКПОТ!!! Три одинаковых!\n"
|
||
f"Множитель: x{multiplier}\n"
|
||
f"Выигрыш: +{winnings:.1f} см\n"
|
||
f"📏 Текущий размер: {new_length:.1f} см"
|
||
)
|
||
return (
|
||
f"🎰 {slots_display}\n\n"
|
||
f"✅ Выигрыш! Две совпали.\n"
|
||
f"Множитель: x{multiplier}\n"
|
||
f"Выигрыш: +{winnings:.1f} см\n"
|
||
f"📏 Текущий размер: {new_length:.1f} см"
|
||
)
|
||
else:
|
||
new_length = update_user_length(user_id, -bet)
|
||
if new_length is None:
|
||
return "Ошибка БД. Попробуй позже."
|
||
return (
|
||
f"🎰 {slots_display}\n\n"
|
||
f"❌ Мимо, братуха.\n"
|
||
f"Проигрыш: -{bet:.1f} см\n"
|
||
f"📏 Текущий размер: {new_length:.1f} см"
|
||
)
|