Files
limoka/vsecoder/hikka_modules/mazemod.py
2025-07-10 21:02:34 +03:00

262 lines
8.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
_
__ _____ ___ ___ ___ __| | ___ _ __
\ \ / / __|/ _ \/ __/ _ \ / _` |/ _ \ '__|
\ V /\__ \ __/ (_| (_) | (_| | __/ |
\_/ |___/\___|\___\___/ \__,_|\___|_|
Copyleft 2022 t.me/vsecoder
This program is free software; you can redistribute it and/or modify
"""
# meta developer: @vsecoder_m
# meta pic: https://img.icons8.com/external-icongeek26-linear-colour-icongeek26/344/external-maze-game-development-icongeek26-linear-colour-icongeek26.png
# meta banner: https://chojuu.vercel.app/api/banner?img=https://img.icons8.com/external-icongeek26-linear-colour-icongeek26/344/external-maze-game-development-icongeek26-linear-colour-icongeek26.png&title=MazeMod&description=Telegram%20Maze%20Game
__version__ = (2, 0, 0)
import logging
import random
from telethon import TelegramClient
from .. import loader # type: ignore
from ..inline.types import InlineCall # type: ignore
logger = logging.getLogger(__name__)
class Maze:
def __init__(self, rowsNumber, columnsNumber):
self.rowsNumber = rowsNumber
self.columnsNumber = columnsNumber
self.maze = []
def isEven(self, number):
return number % 2 == 0
def getRandomFrom(self, array):
return random.choice(array)
def setField(self, x, y, value):
if x < 0 or x >= self.columnsNumber or y < 0 or y >= self.rowsNumber:
return False
self.maze[y][x] = value
def getField(self, x, y):
if x < 0 or x >= self.columnsNumber or y < 0 or y >= self.rowsNumber:
return False
return self.maze[y][x]
def isMaze(self):
for x in range(self.columnsNumber):
for y in range(self.rowsNumber):
if self.isEven(x) and self.isEven(y) and self.getField(x, y) == "⬜️":
return False
return True
def moveTractor(self, tractor):
directs = []
if tractor["x"] > 0:
directs.append("left")
n = self.columnsNumber - 2
if tractor["x"] < n:
directs.append("right")
if tractor["y"] > 0:
directs.append("up")
n = self.rowsNumber - 2
if tractor["y"] < n:
directs.append("down")
direct = self.getRandomFrom(directs)
if direct == "left":
if self.getField(tractor["x"] - 2, tractor["y"]) == "⬜️":
self.setField(tractor["x"] - 1, tractor["y"], "⬛️")
self.setField(tractor["x"] - 2, tractor["y"], "⬛️")
tractor["x"] -= 2
if direct == "right":
if self.getField(tractor["x"] + 2, tractor["y"]) == "⬜️":
self.setField(tractor["x"] + 1, tractor["y"], "⬛️")
self.setField(tractor["x"] + 2, tractor["y"], "⬛️")
tractor["x"] += 2
if direct == "up":
if self.getField(tractor["x"], tractor["y"] - 2) == "⬜️":
self.setField(tractor["x"], tractor["y"] - 1, "⬛️")
self.setField(tractor["x"], tractor["y"] - 2, "⬛️")
tractor["y"] -= 2
if direct == "down":
if self.getField(tractor["x"], tractor["y"] + 2) == "⬜️":
self.setField(tractor["x"], tractor["y"] + 1, "⬛️")
self.setField(tractor["x"], tractor["y"] + 2, "⬛️")
tractor["y"] += 2
def generate_map(self):
for _ in range(self.rowsNumber):
row = ["⬜️" for _ in range(self.columnsNumber)]
self.maze.append(row)
evenColums = []
for column in range(self.columnsNumber):
if self.isEven(column):
evenColums.append(column)
startX = 2
startY = 2
tractor = {"x": startX, "y": startY}
self.setField(startX, startY, "⬛️")
while not self.isMaze():
self.moveTractor(tractor)
return self.maze
@loader.tds
class MazeModMod(loader.Module):
"""Module for play maze"""
strings = {
"name": "MazeMod",
"cfg_maze_width": "Maze width and height, default is 30x30",
"answer": "🕹 <b>Click on the inline buttons to move:</b> <i>{0}</i>",
"doc": "\n 🟦 - player \n ⬛️ - road\n ⬜️ - wall\n 🟩 - finish\n",
"move": "▶️ Moved\n",
"not_allowed": "💭 Not allowed\n",
"win": "🎉 You win!",
"error": "❗️ Error!",
}
strings_ru = {
"answer": "🕹 <b>Нажимайте на инлайн кнопки что двигаться:</b> <i>{0}</i>",
"doc": "\n 🟦 - игрок \n ⬛️ - дорога\n ⬜️ - стена\n 🟩 - финиш\n",
"move": "▶️ Передвинулся\n",
"not_allowed": "💭 Не разрешено\n",
"win": "🎉 Вы победили!",
"error": "❗️ Ошибка!",
}
def __init__(self):
self.config = loader.ModuleConfig(
"maze_width",
"10",
self.strings["cfg_maze_width"],
)
self.name = self.strings["name"]
async def client_ready(self, client: TelegramClient, db):
self._db = db
self._client = client
async def render(self, message: InlineCall, press, maze, player):
text = self.strings["answer"].format(self.strings["not_allowed"])
move = {"x": player["x"], "y": player["y"]}
if press == "up":
move["y"] = move["y"] - 1
if press == "left":
move["x"] = move["x"] - 1
if press == "down":
move["y"] = move["y"] + 1
if press == "right":
move["x"] = move["x"] + 1
if maze[move["y"]][move["x"]] == "":
pass
elif maze[move["y"]][move["x"]] == "⬛️":
maze[player["y"]][player["x"]] = "⬛️"
player = move
text = self.strings["answer"].format(self.strings["move"])
elif maze[move["y"]][move["x"]] == "🟩":
text = self.strings["win"]
return await message.edit(text=text)
maze[player["y"]][player["x"]] = "🟦"
keyboard = [
[
{"text": "🔼", "callback": self.render, "args": ["up", maze, player]},
],
[
{"text": "◀️", "callback": self.render, "args": ["left", maze, player]},
{
"text": "▶️",
"callback": self.render,
"args": ["right", maze, player],
},
],
[
{"text": "🔽", "callback": self.render, "args": ["down", maze, player]},
],
]
for column in maze:
for row in column:
for i in row:
text = text + i
text = text + "\n"
await message.edit(text=text, reply_markup=keyboard)
@loader.unrestricted
@loader.ratelimit
async def mazecmd(self, message):
"""
- generate maze and start play
Based on... my code)
"""
size = int(self.config["maze_width"])
generate = Maze(size, size)
maze = generate.generate_map()
player = {"x": 0, "y": 0}
maze[player["y"]][player["x"]] = "🟦"
maze[size - 2][size - 2] = "🟩"
text = self.strings["answer"].format(self.strings["doc"])
keyboard = [
[
{"text": "🔼", "callback": self.render, "args": ["up", maze, player]},
],
[
{"text": "◀️", "callback": self.render, "args": ["left", maze, player]},
{
"text": "▶️",
"callback": self.render,
"args": ["right", maze, player],
},
],
[
{
"text": "🔽",
"callback": self.render,
"args": [
"down",
maze,
player,
],
},
],
]
for column in maze:
for row in column:
for i in row:
text = text + i
text = text + "\n"
await message.delete()
await self.inline.form(
text=text,
message=message,
always_allow=[message.from_id],
reply_markup=keyboard,
)