diff --git a/README.md b/README.md
index 10a3436..20c40e1 100644
--- a/README.md
+++ b/README.md
@@ -1,34 +1,34 @@
-# Version 0.9 Beta
-Тестовая версия для GNU Linux и OS Windows (x64).
-Для запуска программы требуется **python 3.6+**!!!
-В релизных версиях есть файл для запуска с консолью (для отладки) и стандартный файл
-Код писался под **OS Windows x64**, однако, в теории код работает и с GNU Linux, однако, автор **не гарантирует** 100% работу под Linux.
-## Советы для работы с ядром
-**Не запускайте скомпилированное ядро!! это может привести к некорректной работе игры!!!**
-Ниже приведён пример конфигурационного файла ядра.
-```json
- {
- "pythonRun": true, # Запуск ядра при помощи python
- "pythonPath_win32": "python ", # Путь к python на OS Windows x64
- "pythonPath_unix": "python3 ", # Путь к python на GNU Linux
- "max_responseTime": 15, # Время ожидания отклика ядра (сек)
- "core_file": "gamecore.py", # Файл ядра
- "log_enable": false # Включить логгирование
- }
-```
-## Методы ядра
-Запросы принимаются через файл **gamestat.json**
-```json
-{
- "status": "method" # Метод
- "request": [] # Тело запроса
-}
-```
-После выполнения запроса, ядро высылает ответ в файле **response.json**
-```json
-{
- "response": [] # Тело ответа
- "response_randomID": [] # random ID
-}
-```
-Подробнее читайте в документации.
+# Version 0.9 Beta
+Тестовая версия для GNU Linux и OS Windows (x64).
+Для запуска программы требуется **python 3.6+**!!!
+В релизных версиях есть файл для запуска с консолью (для отладки) и стандартный файл
+Код писался под **OS Windows x64**, однако, в теории код работает и с GNU Linux, однако, автор **не гарантирует** 100% работу под Linux.
+## Советы для работы с ядром
+**Не запускайте скомпилированное ядро!! это может привести к некорректной работе игры!!!**
+Ниже приведён пример конфигурационного файла ядра.
+```json
+ {
+ "pythonRun": true, # Запуск ядра при помощи python
+ "pythonPath_win32": "python ", # Путь к python на OS Windows x64
+ "pythonPath_unix": "python3 ", # Путь к python на GNU Linux
+ "max_responseTime": 15, # Время ожидания отклика ядра (сек)
+ "core_file": "gamecore.py", # Файл ядра
+ "log_enable": false # Включить логгирование
+ }
+```
+## Методы ядра
+Запросы принимаются через файл **gamestat.json**
+```json
+{
+ "status": "method" # Метод
+ "request": [] # Тело запроса
+}
+```
+После выполнения запроса, ядро высылает ответ в файле **response.json**
+```json
+{
+ "response": [] # Тело ответа
+ "response_randomID": [] # random ID
+}
+```
+Подробнее читайте в документации.
diff --git a/SQLEasy.py b/SQLEasy.py
new file mode 100644
index 0000000..f349ecb
--- /dev/null
+++ b/SQLEasy.py
@@ -0,0 +1,192 @@
+import sqlite3
+
+
+class SQLiteEasyException(Exception):
+ pass
+
+
+def compareKey(DBlist, key, type_of_key=lambda x: x):
+ if not(type(DBlist) is list):
+ raise SQLiteEasyException(f"function compareKey need List object, unsupported type: {type(DBlist)}")
+
+ if len(DBlist) > 0:
+ if key not in DBlist[0]:
+ raise SQLiteEasyException(f"key '{key}' not founded.")
+ DB_Dictonary = dict()
+ for BD in sorted(DBlist, key=lambda List: List[key]):
+ comparedBD = dict()
+ for Key in BD:
+ if not(Key == key):
+ comparedBD[Key] = BD[Key]
+ DB_Dictonary[type_of_key(BD[key])] = comparedBD
+
+ return DB_Dictonary
+
+
+class database:
+ def dict_factory(self, cursor, row):
+ dictDB = {}
+ for idx, col in enumerate(cursor.description):
+ dictDB[col[0]] = row[idx]
+ return dictDB
+
+ def encodeSQLiteType(self, objectum, all_as_str=False):
+ if type(objectum) is str:
+ return "'%s'" % objectum.replace('\'', '\\\'')
+ elif objectum is None and all_as_str:
+ return "''"
+ elif objectum is None:
+ return 'NULL'
+ elif type(objectum) is bool and objectum and all_as_str:
+ return "'TRUE'"
+ elif type(objectum) is bool and objectum:
+ return 'TRUE'
+ elif type(objectum) is bool and not(objectum) and all_as_str:
+ return "'FALSE'"
+ elif type(objectum) is bool and not(objectum):
+ return 'FALSE'
+ elif all_as_str and True in [type(objectum) is int, type(objectum) is float]:
+ return "'%s'" % objectum
+ elif not(all_as_str) and True in [type(objectum) is int, type(objectum) is float]:
+ return objectum
+ else:
+ raise SQLiteEasyException(f"Unsupported type: {type(objectum)}")
+
+ def __init__(self, PATH, DatabaseName=None):
+ self.ConnectedFile = sqlite3.connect(PATH)
+ self.databaseChoosed = DatabaseName
+ self.ConnectedFile.row_factory = self.dict_factory
+ self.act_commit = True
+
+ def toggleCommit(self, value=None):
+ if value in (False, True):
+ self.act_commit = value
+ else:
+ if self.act_commit:
+ self.act_commit = False
+ else:
+ self.act_commit = True
+
+ def commit(self):
+ self.ConnectedFile.commit()
+
+ def getBase(self, DatabaseName=None, elementsFromDB='*'):
+ elementsFromDB = str(elementsFromDB)
+ if DatabaseName is None and self.databaseChoosed is None:
+ raise SQLiteEasyException("Database is not choosed")
+ elif DatabaseName is None and not(self.databaseChoosed is None):
+ dbCursore = self.ConnectedFile.cursor()
+ dbCursore.execute(f"select {elementsFromDB} from {self.databaseChoosed}")
+ return dbCursore.fetchall()
+ else:
+ dbCursore = self.ConnectedFile.cursor()
+ dbCursore.execute(f"select {elementsFromDB} from {DatabaseName}")
+ self.databaseChoosed = DatabaseName
+ return dbCursore.fetchall()
+
+ def pop(self, key, value, DatabaseName=None):
+ if type(value) is str:
+ value = f"'%s'" % value.replace('\'', '\\\'')
+ if DatabaseName is None and not(self.databaseChoosed is None):
+ DatabaseName = self.databaseChoosed
+ elif DatabaseName is None:
+ raise SQLiteEasyException("Database is not choosed")
+ dbCursore = self.ConnectedFile.cursor()
+ dbCursore.execute('DELETE FROM %s\n\nWHERE %s == %s;' % (DatabaseName, key, value))
+ if self.act_commit:
+ self.ConnectedFile.commit()
+
+ def setItem(self, key, newValue, indexKey, value, DatabaseName=None):
+ newValue = self.encodeSQLiteType(newValue)
+ value = self.encodeSQLiteType(value)
+ if DatabaseName is None and not(self.databaseChoosed is None):
+ DatabaseName = self.databaseChoosed
+ elif DatabaseName is None:
+ raise SQLiteEasyException("Database is not choosed")
+ dbCursore = self.ConnectedFile.cursor()
+ if value is None:
+ dbCursore.execute('UPDATE %s SET %s = %s WHERE %s is NULL;' % (DatabaseName, key, newValue, indexKey))
+ else:
+ dbCursore.execute('UPDATE %s SET %s = %s WHERE %s = %s;' % (DatabaseName, key, newValue, indexKey, value))
+ if self.act_commit:
+ self.ConnectedFile.commit()
+
+ def add(self, values, DatabaseName=None):
+ if DatabaseName is None and not(self.databaseChoosed is None):
+ DatabaseName = self.databaseChoosed
+ elif DatabaseName is None:
+ raise SQLiteEasyException("Database is not choosed")
+ if DatabaseName is None and not(self.databaseChoosed is None):
+ DatabaseName = self.databaseChoosed
+ elif DatabaseName is None:
+ raise SQLiteEasyException("Database is not choosed")
+
+ keys = [str(key) for key in values]
+ values = [self.encodeSQLiteType(values[key], all_as_str=True) for key in values]
+
+ dbCursore = self.ConnectedFile.cursor()
+ dbCursore.execute('INSERT INTO %s (%s) VALUES (%s)' % (DatabaseName, ', '.join(keys), ', '.join(values)))
+ if self.act_commit:
+ self.ConnectedFile.commit()
+
+ def uploadFiles(self, binary, DatabaseName=None): # Uwaga! Может работать с ошибками.
+ if not(type(binary) is bytes or type(binary) is bytearray):
+ raise SQLiteEasyException('You can upload only byte or bytearray types!!')
+ dbCursore = self.ConnectedFile.cursor()
+ binary = sqlite3.Binary(binary)
+
+ if DatabaseName is None and not(self.databaseChoosed is None):
+ DatabaseName = self.databaseChoosed
+ elif DatabaseName is None:
+ raise SQLiteEasyException("Database is not choosed")
+ if DatabaseName is None and not(self.databaseChoosed is None):
+ DatabaseName = self.databaseChoosed
+ elif DatabaseName is None:
+ raise SQLiteEasyException("Database is not choosed")
+ # (!) Дописать
+
+ def chooseDataBase(self, DatabaseName):
+ self.getBase(DatabaseName)
+ self.databaseChoosed = DatabaseName
+
+ def currentIndex(self, key, value, DatabaseName=None):
+ if DatabaseName is None and not(self.databaseChoosed is None):
+ DatabaseName = self.databaseChoosed
+ elif DatabaseName is None:
+ raise SQLiteEasyException("Database is not choosed")
+
+ DB = self.getBase(DatabaseName)
+
+ ID = 0
+ for Dictonary in sorted(DB, key=lambda dictonary: dictonary[key]):
+ if Dictonary[key] == value:
+ return ID
+ ID += 1
+
+ def currentValue(self, key, value, DatabaseName=None):
+ if DatabaseName is None and not(self.databaseChoosed is None):
+ DatabaseName = self.databaseChoosed
+ elif DatabaseName is None:
+ raise SQLiteEasyException("Database is not choosed")
+
+ DB = self.getBase(DatabaseName)
+
+ for Dictonary in sorted(DB, key=lambda dictonary: dictonary[key]):
+ if Dictonary[key] == value:
+ return Dictonary
+
+ def getTables(self):
+ dbCursore = self.ConnectedFile.cursor()
+ dbCursore.execute('SELECT name from sqlite_master where type= "table"')
+ return [item['name'] for item in dbCursore.fetchall()]
+
+ def getDict(self):
+ dictonary = dict()
+ tables = self.getTables()
+ for table in tables:
+ dictonary[table] = self.getBase(table)
+ return dictonary
+
+
+def formingTable(dictonary, path):
+ pass # В разработке
\ No newline at end of file
diff --git a/Theory/scheme.png b/Theory/scheme.png
new file mode 100644
index 0000000..fd7dc80
Binary files /dev/null and b/Theory/scheme.png differ
diff --git a/Theory/scheme_noBg.png b/Theory/scheme_noBg.png
new file mode 100644
index 0000000..57da036
Binary files /dev/null and b/Theory/scheme_noBg.png differ
diff --git a/corelib.py b/corelib.py
new file mode 100644
index 0000000..3453c62
--- /dev/null
+++ b/corelib.py
@@ -0,0 +1,168 @@
+import os, sys, json
+
+import threading, Gamecore.guiDrawWaiting
+from PyQt5 import QtCore, QtGui, QtWidgets
+from PyQt5.QtWidgets import *
+from PyQt5.Qt import *
+
+with open('Gamecore/config.json', 'r', encoding='utf-8') as cfg:
+ cfg = json.loads(cfg.read())
+
+if cfg["pythonRun"]:
+ if sys.platform == 'win32':
+ runCoreApp = cfg["pythonPath_win32"]
+ else:
+ runCoreApp = cfg["pythonPath_unix"]
+else:
+ if sys.platform == 'win32':
+ runCoreApp = 'start '
+ else:
+ runCoreApp = './'
+
+
+class tool:
+ def __init__(self):
+ def showGUI():
+ class coreGUI(threading.Thread):
+ def run(self):
+ class app_win(QMainWindow):
+ def __init__(self):
+ super(app_win, self).__init__()
+ self.ui = Gamecore.guiDrawWaiting.Ui_Form()
+ self.ui.setupUi(self)
+ self.show()
+
+ self.app = QApplication([])
+ self.application = app_win()
+ self.app.exec()
+
+ def stop(self):
+ self.application.hide()
+ del self
+
+ thrObj = coreGUI()
+ thrObj.start()
+ return thrObj
+
+ def noneGUI(*args, **kwargs):
+ pass
+
+ def stopGUI(thrObj):
+ thrObj.stop()
+
+ self.showGUI = showGUI
+ self.noneGUI = noneGUI
+ self.stopGUI = stopGUI
+
+ self.wait = self.noneGUI
+ self.resp = self.noneGUI
+
+ def showGUI_wait(self, show=True):
+ if show:
+ print('WARNING! You will be using GUI corelib!!!')
+ self.wait = self.showGUI
+ self.resp = self.stopGUI
+ else:
+ self.wait = self.noneGUI
+ self.resp = self.noneGUI
+
+ def response(self, resp):
+ waitObj = self.wait()
+
+ respf = open('Gamecore/gamestat.json', 'wt', encoding='utf-8')
+ respf.write(json.dumps(resp, indent="\t", ensure_ascii=False))
+ respf.close()
+
+ shellScript = open('runCore.sh', 'wt', encoding='utf-8')
+ print(f"cd Gamecore\n{runCoreApp}{cfg['core_file']}")
+ shellScript.write(f"cd Gamecore\n{runCoreApp}{cfg['core_file']}")
+ shellScript.close()
+ if sys.platform != 'win32':
+ os.system("./runCore.sh")
+ else:
+ os.system("runCore.sh")
+
+ output = open('Gamecore/response.json', 'r', encoding='utf-8')
+ outp = output.read()
+ output.close()
+
+ returnObj = json.loads(outp)
+ self.resp(waitObj)
+ return returnObj
+
+
+tool = tool()
+
+
+def newGame(ID, mines=25, fieldsize=10):
+ return tool.response({
+ "status": "newGame",
+ "request": {
+ "ID": ID,
+ "Mines": mines,
+ "size": fieldsize
+ }
+ })
+
+
+def openItem(gamesession, X, Y):
+ return tool.response({
+ "status": "openItem",
+ "request": {
+ "gamesession": gamesession,
+ "X": X,
+ "Y": Y
+ }
+ })
+
+
+def getGameSession(gamesession):
+ return tool.response({
+ "status": "getGameSession",
+ "request": {
+ "gamesession": gamesession
+ }
+ })
+
+
+def toggleFlag(gamesession, X, Y):
+ return tool.response({
+ "status": "toggleFlag",
+ "request": {
+ "gamesession": gamesession,
+ "X": X,
+ "Y": Y
+ }
+ })
+
+
+class Method:
+ def __init__(self, method, **kwargs):
+ self.method = method
+ self.kwargs = kwargs
+
+ def start(self):
+ return eval(self.method)(**kwargs)
+
+
+class multiMethod:
+ def __init__(self, *methods):
+ self.methods = list(methods)
+
+ def append(self, method):
+ self.methods.append(method)
+
+ def pop(self, index):
+ self.methods.pop(index)
+
+ def __len__(self):
+ return len(self.methods)
+
+ def start(self):
+ request = {"status": 'multiMethod', 'requests': list()}
+ for method in self.methods:
+ request['requests'].append({
+ "status": method.method,
+ "request": method.kwargs
+ })
+ return tool.response(request)
\ No newline at end of file
diff --git a/game.py b/game.py
new file mode 100644
index 0000000..3af9e11
--- /dev/null
+++ b/game.py
@@ -0,0 +1,951 @@
+from PyQt5 import QtCore, QtGui, QtWidgets
+from PyQt5.QtWidgets import *
+from PyQt5.Qt import *
+import SQLEasy, json, os, random, corelib
+import launcher # Интерфейс
+
+
+def game(gameStyle, databaseObj, gamerID, gamehash, muzicOn=True, MINES=random.randint(25, 55)):
+ MINES_COMPR = False
+ import pygame
+
+ corelib.tool.showGUI_wait()
+
+ databaseObj.setItem('lastGame', gameStyle, 'ID', gamerID, DatabaseName='users')
+ # Импорт конфига
+ with open(f"source/{gameStyle}/about.json", 'r', encoding='utf-8') as gameconfig:
+ gameconfig = json.loads(gameconfig.read())
+ # Функции
+
+
+ def checkEnd(field):
+ endgame = True
+ for r in field:
+ for c in r:
+ if c in ('M:O', 'M', 'M:F'):
+ return True
+ if 'R' in c and ':O' not in c:
+ endgame = False
+ return endgame
+
+
+ def checkWin(field, endgamecheck=False):
+ fieldCheck = list()
+ endgame = True
+ for r in field:
+ for c in r:
+ fieldCheck.append(c)
+ if 'R' in c and ':O' not in c:
+ endgame = False
+ if endgamecheck:
+ return 'M:O' not in fieldCheck and endgame
+ else:
+ return 'M:O' not in fieldCheck
+
+
+ def compareFields(old_field, field):
+ if checkWin(field, True):
+ return
+
+ class emptySound:
+ def play(self):
+ pass
+
+ sounds = [
+ emptySound(),
+ pygame.mixer.Sound(f"source/{gameStyle}/openCell.wav"),
+ pygame.mixer.Sound(f"source/{gameStyle}/flag.wav")
+ ]
+
+ actID = 0
+
+ comlete = False
+
+ for rowID in range(len(field)):
+ for cellID in range(len(field[rowID])):
+ if field[rowID][cellID] != old_field[rowID][cellID]:
+ if ':F' in field[rowID][cellID]:
+ actID = 2
+ comlete = True
+ break
+ elif ':O' in field[rowID][cellID] and field[rowID][cellID] != 'M:O':
+ actID = 1
+ comlete = True
+ break
+ if comlete:
+ break
+
+ sounds[actID].play()
+ # Классы игровых объектов
+
+
+ class controlBanner(pygame.sprite.Sprite):
+ def __init__(self, X, Y, platform='XBox', info_contentID=0):
+ infocontent = ['openCell', 'flagCell', 'restart']
+ pygame.sprite.Sprite.__init__(self)
+ self.image = pygame.Surface((228, 77))
+ self.platform = platform
+ self.info_contentID = info_contentID
+ self.image = pygame.image.load(f"source/{gameStyle}/{platform}_{infocontent[info_contentID]}.png")
+ self.rect = self.image.get_rect()
+ self.rect.x = X
+ self.rect.y = Y
+
+ def changePlatform(self, platform):
+ infocontent = ['openCell', 'flagCell', 'restart']
+ self.platform = platform
+ self.image = pygame.image.load(f"source/{gameStyle}/{platform}_{infocontent[self.info_contentID]}.png")
+
+
+ class Border(pygame.sprite.Sprite):
+ def __init__(self, X, Y, borderType='Left'):
+ pygame.sprite.Sprite.__init__(self)
+ self.image = pygame.Surface((228, 77))
+ self.animationFrameTime = 0
+ self.borderType = borderType
+ self.image = pygame.image.load(f"source/{gameStyle}/score_end{borderType}(0).png")
+ self.rect = self.image.get_rect()
+ self.rect.x = X
+ self.rect.y = Y
+
+ def update(self):
+ self.animationFrameTime += 1
+ if self.animationFrameTime >= 45:
+ self.animationFrameTime = 0
+ self.image = pygame.image.load(f"source/{gameStyle}/score_end{self.borderType}({self.animationFrameTime // 15}).png")
+
+
+ class resetButton(pygame.sprite.Sprite):
+ def __init__(self, X, Y):
+ pygame.sprite.Sprite.__init__(self)
+ self.image = pygame.Surface((228, 77))
+ self.hide = 'noHover'
+ self.endStatus = ''
+ self.image = pygame.image.load(f"source/{gameStyle}/resetButton_{self.endStatus}_{self.hide}.png")
+ self.rect = self.image.get_rect()
+ self.x = X
+ self.y = Y
+
+ self.rect.x = X
+ self.rect.y = Y
+
+ def editCond(self, hide=None, endStatus=None):
+ if not(hide is None):
+ self.hide = hide
+ if not(endStatus is None):
+ self.endStatus = endStatus
+
+ self.image = pygame.image.load(f"source/{gameStyle}/resetButton_{self.endStatus}_{self.hide}.png")
+
+ def check_myself_Location(self, X, Y):
+ if X >= self.x and X <= self.x + 32 and Y >= self.y and Y <= self.y + 32:
+ return self
+
+
+ class timerCell(pygame.sprite.Sprite):
+ def __init__(self, X, Y, value='off'):
+ pygame.sprite.Sprite.__init__(self)
+ self.image = pygame.Surface((228, 77))
+ self.value = value
+ self.image = pygame.image.load(f"source/{gameStyle}/score_{value}.png")
+ self.rect = self.image.get_rect()
+ self.rect.x = X
+ self.rect.y = Y
+
+ def editValue(self, value='off'):
+ self.value = value
+ self.image = pygame.image.load(f"source/{gameStyle}/score_{self.value}.png")
+
+ def update(self):
+ self.image = pygame.image.load(f"source/{gameStyle}/score_{self.value}.png")
+
+
+ class tablet(pygame.sprite.Sprite):
+ def __init__(self, X, Y):
+ pygame.sprite.Sprite.__init__(self)
+ self.image = pygame.Surface((228, 77))
+ self.image = pygame.image.load(f"source/{gameStyle}/Tablet.png")
+ self.rect = self.image.get_rect()
+ self.rect.x = X
+ self.rect.y = Y
+
+
+ class fieldCursor(pygame.sprite.Sprite):
+ def __init__(self, X, Y):
+ pygame.sprite.Sprite.__init__(self)
+ self.image = pygame.Surface((32, 32))
+ self.image = pygame.image.load(f"source/{gameStyle}/Cursor.png")
+ self.cellPos = (X, Y)
+ self.rect = self.image.get_rect()
+ self.rect.x = 93 + X * 31
+ self.rect.y = 133 + Y * 31
+
+ def setCell_coord(self, X, Y):
+ self.rect.x = 93 + X * 31
+ self.rect.y = 133 + Y * 31
+ self.cellPos = (X, Y)
+
+
+ class cell(pygame.sprite.Sprite):
+ def __init__(self, X, Y, coords, condition='CLOSED'):
+ pygame.sprite.Sprite.__init__(self)
+ self.image = pygame.Surface((32, 32))
+ self.image = pygame.image.load(f"source/{gameStyle}/closed_cell.png")
+ self.rect = self.image.get_rect()
+ self.rect.x = X
+ self.rect.y = Y
+ self.cellPosition = {
+ "X": coords[0],
+ "Y": coords[1]
+ }
+
+ self.condition = condition
+ self.animationFrameS = 0
+
+ def getCondition(self):
+ return self.condition
+
+ def update(self):
+ if self.condition == 'CLOSED':
+ self.image.blit(pygame.image.load(f"source/{gameStyle}/closed_cell.png"), (0, 0))
+ elif 'num_' in self.condition:
+ number = int(self.condition.split('_')[-1])
+ self.animationFrameS += 1
+ if self.animationFrameS >= 40:
+ self.animationFrameS = 0
+ self.image.blit(pygame.image.load(f"source/{gameStyle}/mines_{number}({self.animationFrameS // 20}).png"), (0, 0))
+ elif self.condition == 'OPENED':
+ self.animationFrameS += 1
+ if self.animationFrameS >= 40:
+ self.animationFrameS = 0
+ self.image.blit(pygame.image.load(f"source/{gameStyle}/open_cell_{self.animationFrameS // 20}.png"), (0, 0))
+ elif self.condition == 'FLAG':
+ self.animationFrameS += 1
+ if self.animationFrameS >= 40:
+ self.animationFrameS = 0
+ self.image.blit(pygame.image.load(f"source/{gameStyle}/flag_{self.animationFrameS // 20}.png"), (0, 0))
+ elif self.condition == 'BOMB':
+ self.animationFrameS += 1
+ if self.animationFrameS >= 40:
+ self.animationFrameS = 0
+ self.image.blit(pygame.image.load(f"source/{gameStyle}/mine_bombed({self.animationFrameS // 20}).png"), (0, 0))
+ elif self.condition == 'DEFUSE':
+ self.animationFrameS += 1
+ if self.animationFrameS >= 40:
+ self.animationFrameS = 0
+ self.image.blit(pygame.image.load(f"source/{gameStyle}/mine_finded({self.animationFrameS // 20}).png"), (0, 0))
+
+ def setCondition(self, value):
+ self.condition = value
+
+
+ class sceneGame(pygame.sprite.Group):
+ def __init__(self, platform):
+ pygame.sprite.Group.__init__(self)
+ # Sounds
+ self.bombSound = pygame.mixer.Sound(f"source/{gameStyle}/bomb.wav")
+ self.winSound = pygame.mixer.Sound(f"source/{gameStyle}/win.wav")
+
+ self.soundNotPlayed = True
+
+ self.PLATFORM = platform
+ self.cells = list()
+ for row in range(10):
+ self.cells.append(list())
+ for _cell in range(10):
+ addCell = cell(93 + _cell * 31, 133 + row * 31, (_cell, row))
+ self.add(addCell)
+ self.cells[-1].append({
+ "cellObject": addCell,
+ "coord_start": [93 + _cell * 31, 133 + row * 31],
+ "coord_last": [93 + (_cell + 1) * 31, 133 + (row + 1) * 31],
+ "coords_in_field": (_cell, row)
+ })
+ self.add(tablet(130, 14))
+ self.positionCursor = (0, 0)
+ self.cursor = fieldCursor(*self.positionCursor)
+ self.add(self.cursor)
+ self.add(Border(166, 93))
+ self.timeCells = list()
+ for i in range(3):
+ timerCellObj = timerCell(198 + i * 32, 93)
+ self.add(timerCellObj)
+ self.timeCells.append(timerCellObj)
+ self.add(Border(294, 93, 'Right'))
+ self.resetButton = resetButton(228, 448)
+ self.add(self.resetButton)
+
+ self.InfoTables = list()
+
+ for i in range(3):
+ control_banner = controlBanner(0, 404 + i * 32, platform, i)
+ self.add(control_banner)
+ self.InfoTables.append(control_banner)
+
+ def changePlatform(self, PLATFORM):
+ self.PLATFORM = PLATFORM
+ for tableObj in self.InfoTables:
+ tableObj.changePlatform(PLATFORM)
+
+ def setScoreBoard_value(self, value=None):
+ if not(value is None):
+ value = str(value)
+ if len(value) == 1:
+ value = '00' + value
+ elif len(value) == 2:
+ value = '0' + value
+
+ for numID in range(len(value)):
+ self.timeCells[numID].editValue(int(value[numID]))
+ else:
+ for cellT in self.timeCells:
+ cellT.editValue()
+
+ def getCell_intoCoords(self, x, y):
+ for row in self.cells:
+ for _cell in row:
+ if (x >= _cell["coord_start"][0] and x <= _cell["coord_last"][0]) and (y >= _cell["coord_start"][1] and y <= _cell["coord_last"][1]):
+ return _cell["cellObject"]
+
+ def cursorMove(self, x, y):
+ self.positionCursor = (x, y)
+ self.cursor.setCell_coord(x, y)
+
+ def get_cursorPos(self):
+ return list(self.positionCursor)
+
+ def updateField(self, field, gamefinished=None):
+ global MINES_COMPR
+
+ listcells = list()
+ for r in field:
+ for c in r:
+ listcells.append(c)
+ if gamefinished is None:
+ gamefinished = 'M:O' in listcells
+
+ for rowId in range(len(field)):
+ row = field[rowId]
+ for cellID in range(len(field[rowId])):
+ _cell = field[rowId][cellID]
+
+ actCell = self.cells[rowId][cellID]["cellObject"]
+ if ':O' in _cell:
+ if not(gamefinished):
+ gamefinished = _cell == 'M:O'
+
+ if _cell == 'M:O':
+ actCell.setCondition('BOMB')
+ else:
+ SeeUp = rowId != 0
+ SeeDown = rowId != len(field) - 1
+ SeeLeft = cellID != 0
+ SeeRight = cellID != len(field) - 1
+
+ mines = 0
+ frontire = False
+ if SeeUp:
+ if field[rowId - 1][cellID] in ('M', 'M:F', 'M:O'):
+ mines += 1
+ if not(frontire):
+ frontire = _cell != field[rowId - 1][cellID] and ':O' not in field[rowId - 1][cellID]
+ if SeeDown:
+ if field[rowId + 1][cellID] in ('M', 'M:F', 'M:O'):
+ mines += 1
+ if not(frontire):
+ frontire = _cell != field[rowId + 1][cellID] and ':O' not in field[rowId + 1][cellID]
+ if SeeLeft:
+ if field[rowId][cellID - 1] in ('M', 'M:F', 'M:O'):
+ mines += 1
+ if not(frontire):
+ frontire = _cell != field[rowId][cellID - 1] and ':O' not in field[rowId][cellID - 1]
+ if SeeRight:
+ if field[rowId][cellID + 1] in ('M', 'M:F', 'M:O'):
+ mines += 1
+ if not(frontire):
+ frontire = _cell != field[rowId][cellID + 1] and ':O' not in field[rowId][cellID + 1]
+ # Диагонали
+ if SeeUp and SeeLeft:
+ if field[rowId - 1][cellID - 1] in ('M', 'M:F', 'M:O'):
+ mines += 1
+ if SeeUp and SeeRight:
+ if field[rowId - 1][cellID + 1] in ('M', 'M:F', 'M:O'):
+ mines += 1
+ if SeeDown and SeeLeft:
+ if field[rowId + 1][cellID - 1] in ('M', 'M:F', 'M:O'):
+ mines += 1
+ if SeeDown and SeeRight:
+ if field[rowId + 1][cellID + 1] in ('M', 'M:F', 'M:O'):
+ mines += 1
+
+ if mines > 0:
+ actCell.setCondition('num_%s' % mines)
+ elif frontire:
+ actCell.setCondition('num_1')
+ else:
+ actCell.setCondition('OPENED')
+ elif ':F' in _cell:
+ if gamefinished and _cell == 'M:F':
+ actCell.setCondition('DEFUSE')
+ else:
+ actCell.setCondition('FLAG')
+ else:
+ actCell.setCondition('CLOSED')
+ if not(gamefinished):
+ self.resetButton.editCond(endStatus='')
+ elif checkWin(field):
+ MINES_COMPR = True
+ self.resetButton.editCond(endStatus='win')
+ self.winSound.play()
+ minesDefused = 0
+ scores = 0
+
+ for row in field:
+ for _cell in row:
+ if _cell == 'M:F':
+ minesDefused += 1
+
+ for row in field:
+ for _cell in row:
+ if _cell == 'M:F':
+ if (minesDefused // 5) ** 2 > 15:
+ scores += (minesDefused // 5) ** 2 > 10
+ else:
+ scores += 15
+
+ databaseObj.setItem(
+ 'minesDefuse',
+ SQLEasy.compareKey(databaseObj.getBase('users'), 'ID')[gamerID]['minesDefuse'] + minesDefused,
+ 'ID',
+ gamerID,
+ DatabaseName='users'
+ )
+
+ databaseObj.setItem(
+ 'points',
+ SQLEasy.compareKey(databaseObj.getBase('users'), 'ID')[gamerID]['points'] + scores,
+ 'ID',
+ gamerID,
+ DatabaseName='users'
+ )
+ else:
+ MINES_COMPR = True
+ self.resetButton.editCond(endStatus='lose')
+ self.bombSound.play()
+
+ minesDefused = 0
+ scores = 0
+
+ for row in field:
+ for _cell in row:
+ if _cell == 'M:F':
+ minesDefused += 1
+ scores += 10
+
+ databaseObj.setItem(
+ 'minesDefuse',
+ SQLEasy.compareKey(databaseObj.getBase('users'), 'ID')[gamerID]['minesDefuse'] + minesDefused,
+ 'ID',
+ gamerID,
+ DatabaseName='users'
+ )
+
+ databaseObj.setItem(
+ 'points',
+ SQLEasy.compareKey(databaseObj.getBase('users'), 'ID')[gamerID]['points'] + scores,
+ 'ID',
+ gamerID,
+ DatabaseName='users'
+ )
+
+
+ # код игры
+ logicGame = corelib.getGameSession(gamehash)['response']
+ gamesession = logicGame["gamesession"]
+ field = logicGame["map"]
+
+ if gamesession not in SQLEasy.compareKey(databaseObj.getBase('gamehashes'), 'hash'):
+ databaseObj.add({
+ "hash": gamesession,
+ "userID": gamerID,
+ "mines": MINES,
+ "game": gameStyle,
+ "fieldJSON": json.dumps(field, indent="\t", ensure_ascii=False)
+ }, 'gamehashes')
+
+ pygame.init()
+
+ screen = pygame.display.set_mode((500, 500))
+
+ pygame.display.set_caption(gameconfig['title'])
+ pygame.display.set_icon(pygame.image.load(f"source/{gameStyle}/gameico.png"))
+ bg = pygame.image.load(f"source/{gameStyle}/bg.png")
+ screen.blit(bg, (0, 0))
+
+ PLATFORM = 'XBox' # (!) Сделать проверку
+ # Прорисовка полей
+ sceneGame = sceneGame(PLATFORM)
+
+ pygame.display.flip()
+
+ program_running = True
+
+ cursor_moveUp = False
+ cursor_moveDown = False
+ cursor_moveLeft = False
+ cursor_moveRight = False
+
+ # Muzic
+ pygame.mixer.music.load(f"source/{gameStyle}/muzic.wav")
+ if muzicOn:
+ pygame.mixer.music.play()
+ pygame.mixer.Sound(f"source/{gameStyle}/resetField.wav").play()
+ databaseObj.setItem(
+ 'games',
+ SQLEasy.compareKey(databaseObj.getBase('users'), 'ID')[gamerID]['games'] + 1,
+ 'ID',
+ gamerID,
+ DatabaseName='users'
+ )
+
+ sceneGame.updateField(field)
+
+ while program_running:
+ pygame.time.Clock().tick(60) # max FPS
+ for event in pygame.event.get():
+ if event.type == pygame.QUIT:
+ program_running = False
+ break
+ elif event.type == pygame.MOUSEMOTION:
+ POSITION = event.pos
+ cellSel = sceneGame.getCell_intoCoords(int(POSITION[0]), int(POSITION[1]))
+
+ resetButtonSel = sceneGame.resetButton.check_myself_Location(int(POSITION[0]), int(POSITION[1]))
+ if not(cellSel is None):
+ sceneGame.cursorMove(cellSel.cellPosition["X"], cellSel.cellPosition["Y"])
+ del POSITION, cellSel
+ if not(resetButtonSel is None):
+ resetButtonSel.editCond(hide='hover')
+ else:
+ sceneGame.resetButton.editCond(hide='noHover')
+ elif event.type == pygame.KEYDOWN:
+ cursor_moveUp = event.key == 1073741906
+ cursor_moveDown = event.key == 1073741905
+ cursor_moveLeft = event.key == 1073741904
+ cursor_moveRight = event.key == 1073741903
+
+ cursor_coords = sceneGame.get_cursorPos()
+ if cursor_moveUp:
+ cursor_coords[1] -= 1
+ if cursor_moveDown:
+ cursor_coords[1] += 1
+ if cursor_moveLeft:
+ cursor_coords[0] -= 1
+ if cursor_moveRight:
+ cursor_coords[0] += 1
+
+ if cursor_coords[0] <= -1:
+ cursor_coords[0] = 9
+ if cursor_coords[0] >= 10:
+ cursor_coords[0] = 0
+ if cursor_coords[1] <= -1:
+ cursor_coords[1] = 9
+ if cursor_coords[1] >= 10:
+ cursor_coords[1] = 0
+
+ sceneGame.cursorMove(*cursor_coords)
+ elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
+ POSITION = event.pos
+ cellSel = sceneGame.getCell_intoCoords(int(POSITION[0]), int(POSITION[1]))
+
+ resetButtonSel = sceneGame.resetButton.check_myself_Location(int(POSITION[0]), int(POSITION[1]))
+ if not(cellSel is None):
+ corelib.openItem(gamesession, X=cellSel.cellPosition["X"], Y=cellSel.cellPosition["Y"])
+ respObj = corelib.getGameSession(gamesession)['response']
+ old_field = field
+ field = respObj['map']
+ compareFields(old_field, field)
+ sceneGame.updateField(field, gamefinished=not(respObj['continue']))
+ del POSITION, cellSel
+ if not(resetButtonSel is None):
+ pygame.mixer.Sound(f"source/{gameStyle}/resetField.wav").play()
+ MINES = random.randint(25, 55)
+ logicGame = corelib.newGame(gamerID, mines=MINES)['response']
+ gamesession = logicGame["gamesession"]
+ sceneGame.updateField(logicGame["map"])
+ if muzicOn:
+ pygame.mixer.music.play()
+ MINES_COMPR = False
+
+ databaseObj.setItem(
+ 'games',
+ SQLEasy.compareKey(databaseObj.getBase('users'), 'ID')[gamerID]['games'] + 1,
+ 'ID',
+ gamerID,
+ DatabaseName='users')
+
+ databaseObj.add({
+ "hash": gamesession,
+ "userID": gamerID,
+ "game": gameStyle,
+ "mines": MINES,
+ "fieldJSON": json.dumps(field, indent="\t", ensure_ascii=False)
+ }, 'gamehashes')
+ elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 3:
+ POSITION = event.pos
+ cellSel = sceneGame.getCell_intoCoords(int(POSITION[0]), int(POSITION[1]))
+ if not(cellSel is None):
+ if MINES > 0 and cellSel.getCondition() == 'CLOSED' and not(MINES_COMPR):
+ if 'response' in corelib.toggleFlag(gamesession, X=cellSel.cellPosition["X"], Y=cellSel.cellPosition["Y"]):
+ MINES -= 1
+ respObj = corelib.getGameSession(gamesession)['response']
+ old_field = field
+ field = respObj['map']
+ compareFields(old_field, field)
+ sceneGame.updateField(field, gamefinished=not(respObj['continue']))
+ del POSITION, cellSel
+ elif cellSel.getCondition() == 'FLAG' and not(MINES_COMPR):
+ if 'response' in corelib.toggleFlag(gamesession, X=cellSel.cellPosition["X"], Y=cellSel.cellPosition["Y"]):
+ MINES += 1
+ respObj = corelib.getGameSession(gamesession)['response']
+ old_field = field
+ field = respObj['map']
+ compareFields(old_field, field)
+ sceneGame.updateField(field, gamefinished=not(respObj['continue']))
+ del POSITION, cellSel
+ databaseObj.setItem(
+ 'mines',
+ MINES,
+ 'hash',
+ gamesession,
+ DatabaseName='gamehashes'
+ )
+
+ sceneGame.setScoreBoard_value(MINES)
+
+ sceneGame.draw(screen)
+ sceneGame.update()
+ pygame.display.flip()
+
+ pygame.quit()
+
+
+def getGamesDict():
+ listGames = dict()
+ for directory in [f for f in os.listdir('source') if len(f.split('.')) == 1]:
+ if 'about.json' in os.listdir(f"source/{directory}"):
+ f = open(f"source/{directory}/about.json", 'r', encoding='utf-8')
+ content = json.loads(f.read())
+ listGames[directory] = {
+ "gamename": content['title'],
+ "path": f"source/{directory}"
+ }
+ return listGames
+
+
+def getGameName(name):
+ if name in getGamesDict():
+ return getGamesDict()[name]["gamename"]
+ else:
+ return 'Game not founded.'
+
+
+class app_win(QMainWindow):
+ def __init__(self):
+ super(app_win, self).__init__()
+ self.ui = launcher.Ui_Form()
+ self.ui.setupUi(self)
+
+ self.database = SQLEasy.database('gameDataBase.db')
+
+ # Во-первых, наполним список игроков
+ self.ui.StatTable.removeRow(0)
+ rowPosition = 0
+ for user in self.database.getBase(DatabaseName='users'):
+ self.ui.StatTable.insertRow(rowPosition)
+ self.ui.StatTable.setItem(rowPosition, 0, QTableWidgetItem(user["username"]))
+ self.ui.StatTable.setItem(rowPosition, 1, QTableWidgetItem(str(user["points"])))
+ self.ui.StatTable.setItem(rowPosition, 2, QTableWidgetItem(str(user["minesDefuse"])))
+ if user["games"] != 0:
+ st = str(user["minesDefuse"] // user["games"])
+ else:
+ st = '0'
+ self.ui.StatTable.setItem(rowPosition, 3, QTableWidgetItem(st))
+ self.ui.StatTable.setItem(rowPosition, 4, QTableWidgetItem(getGameName(user["lastGame"])))
+
+ rowPosition += 1
+ self.ui.usernamesList.clear()
+ self.accs = list()
+ for user in self.database.getBase(DatabaseName='users'): # Обновляем во вкладке Профили
+ self.ui.usernamesList.addItem(user["username"])
+ self.accs.append(user)
+
+ # Заполним список вариаций сапёра
+ self.ui.gameList.clear()
+ for gameDir in getGamesDict():
+ item = QtWidgets.QListWidgetItem(getGamesDict()[gameDir]['gamename'])
+ icon1 = QtGui.QIcon()
+ icon1.addPixmap(QtGui.QPixmap(f"source/{gameDir}/gameico.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ item.setIcon(icon1)
+ self.ui.gameList.addItem(item)
+
+ self.show()
+
+ self.ui.usernamesList.doubleClicked.connect(self.importLogin)
+ self.ui.regButton.clicked.connect(self.register)
+ self.ui.loginButton.clicked.connect(self.logIn)
+ self.ui.play.clicked.connect(self.play)
+ self.ui.logOut.clicked.connect(self.logOut)
+ self.ui.updateGames.clicked.connect(self.upDate_sapers)
+ self.ui.loadGame.clicked.connect(self.LoadGame)
+ # Список сохранений...
+ self.ui.SaveList.clear()
+ self.savedGames = list()
+
+ multiMethod = corelib.multiMethod()
+
+ for save in self.database.getBase('gamehashes'):
+ if save['game'] in getGamesDict() and save['userID'] == self.database.getBase('gamedata')[0]['activeprofile']:
+ multiMethod.append(corelib.Method('getGameSession', gamesession=save['hash']))
+
+ resp = multiMethod.start()['responses']
+ respID = -1
+
+ for save in self.database.getBase('gamehashes'):
+ if save['game'] in getGamesDict() and save['userID'] == self.database.getBase('gamedata')[0]['activeprofile']:
+ respID += 1
+ if 'response' in resp[respID]:
+ if resp[respID]['response']['continue']:
+ item = QtWidgets.QListWidgetItem(
+ f"{getGamesDict()[save['game']]['gamename']}, мин: {save['mines']}"
+ )
+ icon1 = QtGui.QIcon()
+ icon1.addPixmap(QtGui.QPixmap(f"source/{save['game']}/gameico.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ item.setIcon(icon1)
+ self.ui.SaveList.addItem(item)
+ self.savedGames.append([
+ save['hash'],
+ save['mines'],
+ save['game']
+ ])
+
+ # Сделаем таймер
+
+ self.timer = QtCore.QTimer(self)
+ self.timer.timeout.connect(self.timerVoid)
+ self.timer.start(1)
+
+ def upDate_sapers(self):
+ self.ui.gameList.clear()
+ for gameDir in getGamesDict():
+ item = QtWidgets.QListWidgetItem(getGamesDict()[gameDir]['gamename'])
+ icon1 = QtGui.QIcon()
+ icon1.addPixmap(QtGui.QPixmap(f"source/{gameDir}/gameico.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ item.setIcon(icon1)
+ self.ui.gameList.addItem(item)
+
+ def logOut(self):
+ self.database.setItem(
+ 'activeprofile',
+ '-',
+ 'ID',
+ 1,
+ DatabaseName='gamedata')
+ self.ui.SaveList.clear()
+ QMessageBox.information(self, 'Успех!', 'Вы успешно вышли!!!', QMessageBox.Ok)
+
+ def logIn(self):
+ if self.ui.loginUsernameLine.text() in [user['username'] for user in self.database.getBase('users')]:
+ if SQLEasy.compareKey(self.database.getBase('users'), key='username')[self.ui.loginUsernameLine.text()]['password'] is None:
+ self.database.setItem(
+ 'activeprofile',
+ SQLEasy.compareKey(self.database.getBase('users'), key='username')[self.ui.loginUsernameLine.text()]['ID'],
+ 'ID',
+ 1,
+ DatabaseName='gamedata')
+ QMessageBox.information(self, 'Успех!', 'Вы успешно вошли!!!', QMessageBox.Ok)
+ elif SQLEasy.compareKey(self.database.getBase('users'), key='username')[self.ui.loginUsernameLine.text()]['password'] == self.ui.loginHasloLine.text():
+ self.database.setItem(
+ 'activeprofile',
+ SQLEasy.compareKey(self.database.getBase('users'), key='username')[self.ui.loginUsernameLine.text()]['ID'],
+ 'ID',
+ 1,
+ DatabaseName='gamedata')
+ QMessageBox.information(self, 'Успех!', 'Вы успешно вошли!!!', QMessageBox.Ok)
+ else:
+ QMessageBox.critical(self, 'Упс...', 'Неверный пароль!', QMessageBox.Ok)
+ else:
+ QMessageBox.critical(self, 'Упс...', 'Такого пользователя просто нет :(', QMessageBox.Ok)
+
+ self.ui.SaveList.clear()
+ self.savedGames = list()
+
+ multiMethod = corelib.multiMethod()
+
+ for save in self.database.getBase('gamehashes'):
+ if save['game'] in getGamesDict() and save['userID'] == self.database.getBase('gamedata')[0]['activeprofile']:
+ multiMethod.append(corelib.Method('getGameSession', gamesession=save['hash']))
+
+ resp = multiMethod.start()['responses']
+ respID = -1
+
+ for save in self.database.getBase('gamehashes'):
+ if save['game'] in getGamesDict() and save['userID'] == self.database.getBase('gamedata')[0]['activeprofile']:
+ respID += 1
+ if 'response' in resp[respID]:
+ if resp[respID]['response']['continue']:
+ item = QtWidgets.QListWidgetItem(
+ f"{getGamesDict()[save['game']]['gamename']}, мин: {save['mines']}"
+ )
+ icon1 = QtGui.QIcon()
+ icon1.addPixmap(QtGui.QPixmap(f"source/{save['game']}/gameico.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ item.setIcon(icon1)
+ self.ui.SaveList.addItem(item)
+ self.savedGames.append([
+ save['hash'],
+ save['mines'],
+ save['game']
+ ])
+
+ def register(self):
+ if self.ui.regLoginLine.text() in [user['username'] for user in self.database.getBase('users')]:
+ QMessageBox.critical(self, 'Упс...', 'Есть такой пользователь, ЕСТЬ!!!', QMessageBox.Ok)
+ return
+ if len(self.ui.regHasloLine.text()) > 0:
+ if len(self.ui.regHasloLine.text()) >= 65:
+ QMessageBox.warning(self, 'Warning!', 'Too many symbols on password!', QMessageBox.Ok)
+ return
+
+ if len(self.ui.regLoginLine.text()) >= 65:
+ QMessageBox.warning(self, 'Warning!', 'Too many symbols on login!', QMessageBox.Ok)
+ return
+
+ self.database.add({
+ "ID": len(self.database.getBase('users')),
+ "username": self.ui.regLoginLine.text()
+ }, 'users')
+ QMessageBox.information(self, 'Успех!', 'Профиль создан!', QMessageBox.Ok)
+
+ self.ui.usernamesList.clear()
+ self.accs = list()
+ for user in self.database.getBase(DatabaseName='users'): # Обновляем во вкладке Профили
+ self.ui.usernamesList.addItem(user["username"])
+ self.accs.append(user)
+
+ def importLogin(self):
+ if self.ui.usernamesList.currentRow() >= 0 and self.ui.usernamesList.currentRow() < len(self.ui.usernamesList):
+ user = self.accs[self.ui.usernamesList.currentRow()]
+ self.ui.loginUsernameLine.setText(user['username'])
+
+ def LoadGame(self):
+ global game
+
+ self.hide()
+ hashK = self.savedGames[self.ui.SaveList.currentRow()][0]
+ mines = self.savedGames[self.ui.SaveList.currentRow()][1]
+
+ game(
+ self.savedGames[self.ui.SaveList.currentRow()][2],
+ gamerID=self.database.getBase('gamedata')[0]['activeprofile'],
+ databaseObj=self.database,
+ gamehash=hashK,
+ MINES=mines,
+ muzicOn=self.ui.soundOn.isChecked()
+ )
+ os.abort()
+ del self
+
+
+ def play(self):
+ global game
+
+ self.hide()
+ hashK = corelib.newGame(ID=self.database.getBase('gamedata')[0]['activeprofile'], mines=25, fieldsize=10)['response']
+ mines = random.randint(25, 55)
+
+ game(
+ [k for k in getGamesDict()][self.ui.gameList.currentRow()],
+ gamerID=self.database.getBase('gamedata')[0]['activeprofile'],
+ databaseObj=self.database,
+ gamehash=hashK['gamesession'],
+ MINES=mines,
+ muzicOn=self.ui.soundOn.isChecked()
+ )
+ os.abort()
+ del self
+
+ def timerVoid(self):
+ def getCoorectLogin(string):
+ login = ''
+ for symbol in string:
+ if symbol in '0123456789qwertyuiopasdfghjklzxcvbnm_-.' + 'qwertyuiopasdfghjklzxcvbnm'.upper():
+ login += symbol
+ if len(login) > 64:
+ login = login[:64]
+ return login
+
+ self.ui.play.setEnabled(
+ self.ui.gameList.currentRow() >= 0 and
+ self.ui.gameList.currentRow() < len(self.ui.gameList) and
+ not(self.database.getBase('gamedata')[0]['activeprofile'] is None or self.database.getBase('gamedata')[0]['activeprofile'] == '-')
+ )
+
+ self.ui.logOut.setEnabled(not(self.database.getBase('gamedata')[0]['activeprofile'] is None or self.database.getBase('gamedata')[0]['activeprofile'] == '-'))
+ self.ui.loadGame.setEnabled(len(self.ui.SaveList) > 0)
+
+ if not(self.database.getBase('gamedata')[0]['activeprofile'] is None or self.database.getBase('gamedata')[0]['activeprofile'] == '-'):
+ nickname = SQLEasy.compareKey(self.database.getBase('users'), 'ID')
+ nickname = nickname[self.database.getBase('gamedata')[0]['activeprofile']]['username']
+ self.ui.gameinfo.setText(f"Добро пожаловать, {nickname}!")
+ else:
+ self.ui.gameinfo.setText("Войдите или зарегайте профиль, чтобы играть!")
+
+ self.ui.loginButton.setEnabled(
+ len(self.ui.loginUsernameLine.text()) > 8 and (len(self.ui.loginHasloLine.text()) > 8 or len(self.ui.loginHasloLine.text()) == 0)
+ )
+ self.ui.regButton.setEnabled(
+ len(self.ui.regLoginLine.text()) > 8 and (len(self.ui.regHasloLine.text()) > 8 or len(self.ui.regHasloLine.text()) == 0)
+ )
+
+ if self.ui.loginUsernameLine.text() != getCoorectLogin(self.ui.loginUsernameLine.text()):
+ self.ui.loginUsernameLine.setText(getCoorectLogin(self.ui.loginUsernameLine.text()))
+ if self.ui.regLoginLine.text() != getCoorectLogin(self.ui.regLoginLine.text()):
+ self.ui.regLoginLine.setText(getCoorectLogin(self.ui.regLoginLine.text()))
+ if self.ui.loginHasloLine.text() != getCoorectLogin(self.ui.loginHasloLine.text()):
+ self.ui.loginHasloLine.setText(getCoorectLogin(self.ui.loginHasloLine.text()))
+ if self.ui.regHasloLine.text() != getCoorectLogin(self.ui.regHasloLine.text()):
+ self.ui.regHasloLine.setText(getCoorectLogin(self.ui.regHasloLine.text()))
+
+ if self.ui.logPasShow.isChecked():
+ self.ui.loginHasloLine.setEchoMode(QtWidgets.QLineEdit.Normal)
+ else:
+ self.ui.loginHasloLine.setEchoMode(QtWidgets.QLineEdit.Password)
+
+ if self.ui.regPasShow.isChecked():
+ self.ui.regHasloLine.setEchoMode(QtWidgets.QLineEdit.Normal)
+ else:
+ self.ui.regHasloLine.setEchoMode(QtWidgets.QLineEdit.Password)
+
+ # Запрещаем редактировать стату
+ self.ui.StatTable.setRowCount(0)
+ rowPosition = 0
+ for user in sorted(self.database.getBase(DatabaseName='users'), key=lambda x: x['points'], reverse=True):
+ self.ui.StatTable.insertRow(rowPosition)
+ self.ui.StatTable.setItem(rowPosition, 0, QTableWidgetItem(user["username"]))
+ self.ui.StatTable.setItem(rowPosition, 1, QTableWidgetItem(str(user["points"])))
+ self.ui.StatTable.setItem(rowPosition, 2, QTableWidgetItem(str(user["minesDefuse"])))
+
+ if user["games"] != 0:
+ st = str(user["minesDefuse"] // user["games"])
+ else:
+ st = '0'
+ self.ui.StatTable.setItem(rowPosition, 3, QTableWidgetItem(st))
+ self.ui.StatTable.setItem(rowPosition, 4, QTableWidgetItem(getGameName(user["lastGame"])))
+
+ rowPosition += 1
+
+
+app = QApplication([])
+application = app_win()
+app.exec()
+os.abort()
\ No newline at end of file
diff --git a/gameDataBase.db b/gameDataBase.db
new file mode 100644
index 0000000..d53e4e8
Binary files /dev/null and b/gameDataBase.db differ
diff --git a/icon.ico b/icon.ico
new file mode 100644
index 0000000..42325c2
Binary files /dev/null and b/icon.ico differ
diff --git a/launcher.py b/launcher.py
new file mode 100644
index 0000000..2c763d3
--- /dev/null
+++ b/launcher.py
@@ -0,0 +1,210 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'launcher.ui'
+#
+# Created by: PyQt5 UI code generator 5.15.1
+#
+# WARNING: Any manual changes made to this file will be lost when pyuic5 is
+# run again. Do not edit this file unless you know what you are doing.
+
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+
+
+class Ui_Form(object):
+ def setupUi(self, Form):
+ Form.setObjectName("Form")
+ Form.resize(460, 341)
+ icon = QtGui.QIcon()
+ icon.addPixmap(QtGui.QPixmap("source/gameico.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ Form.setWindowIcon(icon)
+ self.tabWidget = QtWidgets.QTabWidget(Form)
+ self.tabWidget.setGeometry(QtCore.QRect(10, 10, 441, 281))
+ self.tabWidget.setObjectName("tabWidget")
+ self.Launcher = QtWidgets.QWidget()
+ self.Launcher.setObjectName("Launcher")
+ self.gameList = QtWidgets.QListWidget(self.Launcher)
+ self.gameList.setGeometry(QtCore.QRect(20, 30, 391, 171))
+ self.gameList.setObjectName("gameList")
+ item = QtWidgets.QListWidgetItem()
+ icon1 = QtGui.QIcon()
+ icon1.addPixmap(QtGui.QPixmap("source/sys admin/gameico.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ item.setIcon(icon1)
+ self.gameList.addItem(item)
+ self.play = QtWidgets.QPushButton(self.Launcher)
+ self.play.setGeometry(QtCore.QRect(180, 220, 75, 23))
+ self.play.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
+ self.play.setObjectName("play")
+ self.soundOn = QtWidgets.QCheckBox(self.Launcher)
+ self.soundOn.setGeometry(QtCore.QRect(310, 230, 121, 21))
+ self.soundOn.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
+ self.soundOn.setChecked(True)
+ self.soundOn.setObjectName("soundOn")
+ self.updateGames = QtWidgets.QPushButton(self.Launcher)
+ self.updateGames.setGeometry(QtCore.QRect(20, 210, 75, 23))
+ self.updateGames.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
+ self.updateGames.setObjectName("updateGames")
+ self.tabWidget.addTab(self.Launcher, "")
+ self.tab = QtWidgets.QWidget()
+ self.tab.setObjectName("tab")
+ self.StatTable = QtWidgets.QTableWidget(self.tab)
+ self.StatTable.setGeometry(QtCore.QRect(10, 0, 421, 231))
+ self.StatTable.setObjectName("StatTable")
+ self.StatTable.setColumnCount(5)
+ self.StatTable.setRowCount(1)
+ item = QtWidgets.QTableWidgetItem()
+ self.StatTable.setVerticalHeaderItem(0, item)
+ item = QtWidgets.QTableWidgetItem()
+ self.StatTable.setHorizontalHeaderItem(0, item)
+ item = QtWidgets.QTableWidgetItem()
+ self.StatTable.setHorizontalHeaderItem(1, item)
+ item = QtWidgets.QTableWidgetItem()
+ self.StatTable.setHorizontalHeaderItem(2, item)
+ item = QtWidgets.QTableWidgetItem()
+ self.StatTable.setHorizontalHeaderItem(3, item)
+ item = QtWidgets.QTableWidgetItem()
+ self.StatTable.setHorizontalHeaderItem(4, item)
+ item = QtWidgets.QTableWidgetItem()
+ self.StatTable.setItem(0, 0, item)
+ item = QtWidgets.QTableWidgetItem()
+ self.StatTable.setItem(0, 1, item)
+ item = QtWidgets.QTableWidgetItem()
+ self.StatTable.setItem(0, 2, item)
+ item = QtWidgets.QTableWidgetItem()
+ self.StatTable.setItem(0, 3, item)
+ item = QtWidgets.QTableWidgetItem()
+ self.StatTable.setItem(0, 4, item)
+ self.tabWidget.addTab(self.tab, "")
+ self.saves = QtWidgets.QWidget()
+ self.saves.setObjectName("saves")
+ self.SaveList = QtWidgets.QListWidget(self.saves)
+ self.SaveList.setGeometry(QtCore.QRect(10, 10, 411, 211))
+ self.SaveList.setObjectName("SaveList")
+ item = QtWidgets.QListWidgetItem()
+ item.setIcon(icon1)
+ self.SaveList.addItem(item)
+ self.loadGame = QtWidgets.QPushButton(self.saves)
+ self.loadGame.setGeometry(QtCore.QRect(10, 230, 75, 23))
+ self.loadGame.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
+ self.loadGame.setObjectName("loadGame")
+ self.tabWidget.addTab(self.saves, "")
+ self.profiles = QtWidgets.QWidget()
+ self.profiles.setObjectName("profiles")
+ self.groupBox = QtWidgets.QGroupBox(self.profiles)
+ self.groupBox.setGeometry(QtCore.QRect(0, 10, 171, 121))
+ self.groupBox.setObjectName("groupBox")
+ self.loginUsernameLine = QtWidgets.QLineEdit(self.groupBox)
+ self.loginUsernameLine.setGeometry(QtCore.QRect(10, 20, 151, 20))
+ self.loginUsernameLine.setObjectName("loginUsernameLine")
+ self.loginHasloLine = QtWidgets.QLineEdit(self.groupBox)
+ self.loginHasloLine.setGeometry(QtCore.QRect(10, 50, 151, 20))
+ self.loginHasloLine.setEchoMode(QtWidgets.QLineEdit.Password)
+ self.loginHasloLine.setObjectName("loginHasloLine")
+ self.loginButton = QtWidgets.QPushButton(self.groupBox)
+ self.loginButton.setGeometry(QtCore.QRect(90, 90, 75, 23))
+ self.loginButton.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
+ self.loginButton.setObjectName("loginButton")
+ self.logPasShow = QtWidgets.QCheckBox(self.groupBox)
+ self.logPasShow.setGeometry(QtCore.QRect(10, 90, 70, 17))
+ self.logPasShow.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
+ self.logPasShow.setObjectName("logPasShow")
+ self.usernamesList = QtWidgets.QListWidget(self.profiles)
+ self.usernamesList.setGeometry(QtCore.QRect(185, 10, 231, 201))
+ self.usernamesList.setObjectName("usernamesList")
+ item = QtWidgets.QListWidgetItem()
+ self.usernamesList.addItem(item)
+ self.groupBox_2 = QtWidgets.QGroupBox(self.profiles)
+ self.groupBox_2.setGeometry(QtCore.QRect(0, 130, 171, 121))
+ self.groupBox_2.setObjectName("groupBox_2")
+ self.regLoginLine = QtWidgets.QLineEdit(self.groupBox_2)
+ self.regLoginLine.setGeometry(QtCore.QRect(10, 20, 151, 20))
+ self.regLoginLine.setObjectName("regLoginLine")
+ self.regHasloLine = QtWidgets.QLineEdit(self.groupBox_2)
+ self.regHasloLine.setGeometry(QtCore.QRect(10, 50, 151, 20))
+ self.regHasloLine.setEchoMode(QtWidgets.QLineEdit.Password)
+ self.regHasloLine.setObjectName("regHasloLine")
+ self.regButton = QtWidgets.QPushButton(self.groupBox_2)
+ self.regButton.setGeometry(QtCore.QRect(90, 90, 75, 23))
+ self.regButton.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
+ self.regButton.setObjectName("regButton")
+ self.regPasShow = QtWidgets.QCheckBox(self.groupBox_2)
+ self.regPasShow.setGeometry(QtCore.QRect(10, 90, 70, 17))
+ self.regPasShow.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
+ self.regPasShow.setObjectName("regPasShow")
+ self.logOut = QtWidgets.QPushButton(self.profiles)
+ self.logOut.setEnabled(False)
+ self.logOut.setGeometry(QtCore.QRect(330, 230, 75, 23))
+ self.logOut.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
+ self.logOut.setObjectName("logOut")
+ self.tabWidget.addTab(self.profiles, "")
+ self.gameinfo = QtWidgets.QLabel(Form)
+ self.gameinfo.setGeometry(QtCore.QRect(20, 300, 411, 31))
+ self.gameinfo.setObjectName("gameinfo")
+
+ self.retranslateUi(Form)
+ self.tabWidget.setCurrentIndex(0)
+ QtCore.QMetaObject.connectSlotsByName(Form)
+
+ def retranslateUi(self, Form):
+ _translate = QtCore.QCoreApplication.translate
+ Form.setWindowTitle(_translate("Form", "Сапёр игровой лаунчер"))
+ __sortingEnabled = self.gameList.isSortingEnabled()
+ self.gameList.setSortingEnabled(False)
+ item = self.gameList.item(0)
+ item.setText(_translate("Form", "Системный администратор"))
+ self.gameList.setSortingEnabled(__sortingEnabled)
+ self.play.setText(_translate("Form", "Играть"))
+ self.soundOn.setText(_translate("Form", "Включить музыку"))
+ self.updateGames.setText(_translate("Form", "Обновить"))
+ self.tabWidget.setTabText(self.tabWidget.indexOf(self.Launcher), _translate("Form", "Игра"))
+ item = self.StatTable.verticalHeaderItem(0)
+ item.setText(_translate("Form", "1"))
+ item = self.StatTable.horizontalHeaderItem(0)
+ item.setText(_translate("Form", "Никнейм"))
+ item = self.StatTable.horizontalHeaderItem(1)
+ item.setText(_translate("Form", "Очки"))
+ item = self.StatTable.horizontalHeaderItem(2)
+ item.setText(_translate("Form", "Обезврежено мин"))
+ item = self.StatTable.horizontalHeaderItem(3)
+ item.setText(_translate("Form", "Среднее количество обезвреженных мин"))
+ item = self.StatTable.horizontalHeaderItem(4)
+ item.setText(_translate("Form", "Последняя запущена игра..."))
+ __sortingEnabled = self.StatTable.isSortingEnabled()
+ self.StatTable.setSortingEnabled(False)
+ item = self.StatTable.item(0, 0)
+ item.setText(_translate("Form", "Игрок"))
+ item = self.StatTable.item(0, 1)
+ item.setText(_translate("Form", "0"))
+ item = self.StatTable.item(0, 2)
+ item.setText(_translate("Form", "0"))
+ item = self.StatTable.item(0, 3)
+ item.setText(_translate("Form", "0"))
+ item = self.StatTable.item(0, 4)
+ item.setText(_translate("Form", "0"))
+ self.StatTable.setSortingEnabled(__sortingEnabled)
+ self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("Form", "Статистика"))
+ __sortingEnabled = self.SaveList.isSortingEnabled()
+ self.SaveList.setSortingEnabled(False)
+ item = self.SaveList.item(0)
+ item.setText(_translate("Form", "User, 22.09.2003 14:50, Системный администратор (не закончено)"))
+ self.SaveList.setSortingEnabled(__sortingEnabled)
+ self.loadGame.setText(_translate("Form", "Загрузить"))
+ self.tabWidget.setTabText(self.tabWidget.indexOf(self.saves), _translate("Form", "Сохранения"))
+ self.groupBox.setTitle(_translate("Form", "Войти"))
+ self.loginUsernameLine.setPlaceholderText(_translate("Form", "Логин"))
+ self.loginHasloLine.setPlaceholderText(_translate("Form", "Пароль"))
+ self.loginButton.setText(_translate("Form", "Войти"))
+ self.logPasShow.setText(_translate("Form", "Показать"))
+ __sortingEnabled = self.usernamesList.isSortingEnabled()
+ self.usernamesList.setSortingEnabled(False)
+ item = self.usernamesList.item(0)
+ item.setText(_translate("Form", "Игрок"))
+ self.usernamesList.setSortingEnabled(__sortingEnabled)
+ self.groupBox_2.setTitle(_translate("Form", "Зарегистрировать профиль"))
+ self.regLoginLine.setPlaceholderText(_translate("Form", "Логин"))
+ self.regHasloLine.setPlaceholderText(_translate("Form", "Пароль"))
+ self.regButton.setText(_translate("Form", "Регистрация"))
+ self.regPasShow.setText(_translate("Form", "Показать"))
+ self.logOut.setText(_translate("Form", "Выйти"))
+ self.tabWidget.setTabText(self.tabWidget.indexOf(self.profiles), _translate("Form", "Профили"))
+ self.gameinfo.setText(_translate("Form", "Войдите или зарегайте профиль, чтобы играть!"))
diff --git a/launcher.ui b/launcher.ui
new file mode 100644
index 0000000..e0c8fd5
--- /dev/null
+++ b/launcher.ui
@@ -0,0 +1,421 @@
+
+
+ Form
+
+
+
+ 0
+ 0
+ 460
+ 341
+
+
+
+ Сапёр игровой лаунчер
+
+
+
+ source/gameico.icosource/gameico.ico
+
+
+
+
+ 10
+ 10
+ 441
+ 281
+
+
+
+ 0
+
+
+
+ Игра
+
+
+
+
+ 20
+ 30
+ 391
+ 171
+
+
+ -
+
+ Системный администратор
+
+
+
+ source/sys admin/gameico.pngsource/sys admin/gameico.png
+
+
+
+
+
+
+ 180
+ 220
+ 75
+ 23
+
+
+
+ PointingHandCursor
+
+
+ Играть
+
+
+
+
+
+ 310
+ 230
+ 121
+ 21
+
+
+
+ PointingHandCursor
+
+
+ Включить музыку
+
+
+ true
+
+
+
+
+
+ 20
+ 210
+ 75
+ 23
+
+
+
+ PointingHandCursor
+
+
+ Обновить
+
+
+
+
+
+ Статистика
+
+
+
+
+ 10
+ 0
+ 421
+ 231
+
+
+
+
+ 1
+
+
+
+
+ Никнейм
+
+
+
+
+ Очки
+
+
+
+
+ Обезврежено мин
+
+
+
+
+ Среднее количество обезвреженных мин
+
+
+
+
+ Любимая игра
+
+
+ -
+
+ Игрок
+
+
+ -
+
+ 0
+
+
+ -
+
+ 0
+
+
+ -
+
+ 0
+
+
+ -
+
+ 0
+
+
+
+
+
+
+ Сохранения
+
+
+
+
+ 10
+ 10
+ 411
+ 211
+
+
+ -
+
+ User, 22.09.2003 14:50, Системный администратор (не закончено)
+
+
+
+ source/sys admin/gameico.pngsource/sys admin/gameico.png
+
+
+
+
+
+
+ 10
+ 230
+ 75
+ 23
+
+
+
+ PointingHandCursor
+
+
+ Загрузить
+
+
+
+
+
+ Профили
+
+
+
+
+ 0
+ 10
+ 171
+ 121
+
+
+
+ Войти
+
+
+
+
+ 10
+ 20
+ 151
+ 20
+
+
+
+ Логин
+
+
+
+
+
+ 10
+ 50
+ 151
+ 20
+
+
+
+ QLineEdit::Password
+
+
+ Пароль
+
+
+
+
+
+ 90
+ 90
+ 75
+ 23
+
+
+
+ PointingHandCursor
+
+
+ Войти
+
+
+
+
+
+ 10
+ 90
+ 70
+ 17
+
+
+
+ PointingHandCursor
+
+
+ Показать
+
+
+
+
+
+
+ 185
+ 10
+ 231
+ 201
+
+
+ -
+
+ Игрок
+
+
+
+
+
+
+ 0
+ 130
+ 171
+ 121
+
+
+
+ Зарегистрировать профиль
+
+
+
+
+ 10
+ 20
+ 151
+ 20
+
+
+
+ Логин
+
+
+
+
+
+ 10
+ 50
+ 151
+ 20
+
+
+
+ QLineEdit::Password
+
+
+ Пароль
+
+
+
+
+
+ 90
+ 90
+ 75
+ 23
+
+
+
+ PointingHandCursor
+
+
+ Регистрация
+
+
+
+
+
+ 10
+ 90
+ 70
+ 17
+
+
+
+ PointingHandCursor
+
+
+ Показать
+
+
+
+
+
+ false
+
+
+
+ 330
+ 230
+ 75
+ 23
+
+
+
+ PointingHandCursor
+
+
+ Выйти
+
+
+
+
+
+
+
+ 20
+ 300
+ 411
+ 31
+
+
+
+ Войдите или зарегайте профиль, чтобы играть!
+
+
+
+
+
+
diff --git a/runCore.sh b/runCore.sh
new file mode 100644
index 0000000..0f95607
--- /dev/null
+++ b/runCore.sh
@@ -0,0 +1,2 @@
+cd Gamecore
+start gamecore.exe
\ No newline at end of file
diff --git a/testgame.py b/testgame.py
new file mode 100644
index 0000000..398f964
--- /dev/null
+++ b/testgame.py
@@ -0,0 +1,109 @@
+import corelib, os, termcolor, colorama
+colorama.init()
+
+clear = lambda: os.system('cls')
+gamedata = corelib.newGame(ID=0, mines=25, fieldsize=10)['response']
+gamedata['continue'] = True
+clear()
+
+
+def getuserfield(field, gamefinnised=False):
+ maxFieldCoord = len(field) - 1
+ # ░ свободная клетка
+ # █ Не открытая клетка
+ # F Помечена флагом
+ # 1..4 Мины рядом
+ # X Минa взорвана
+ # S Минa обезврежена
+ retfield = list()
+ for row in field:
+ X = field.index(row)
+ retfield.append(list())
+ for cell in row:
+ Y = field[X].index(cell)
+ if ':O' in cell and cell != 'M:O':
+ mines = 0
+ # Проверим наличие мин
+ upCoord = Y != 0
+ downCoord = Y != maxFieldCoord
+ leftCoord = X != 0
+ rightCoord = X != maxFieldCoord
+
+ if upCoord and field[X][Y - 1] != cell and ':O' not in field[X][Y - 1]:
+ mines += 1
+ if downCoord and field[X][Y + 1] != cell and ':O' not in field[X][Y + 1]:
+ mines += 1
+ if leftCoord and field[X - 1][Y] != cell and ':O' not in field[X - 1][Y]:
+ mines += 1
+ if rightCoord and field[X + 1][Y] != cell and ':O' not in field[X + 1][Y]:
+ mines += 1
+ if mines == 0:
+ if upCoord and field[X][Y - 1] != cell:
+ mines = 1
+ elif downCoord and field[X][Y + 1] != cell:
+ mines = 1
+ elif leftCoord and field[X - 1][Y] != cell:
+ mines = 1
+ elif rightCoord and field[X + 1][Y] != cell:
+ mines = 1
+
+ if mines == 0:
+ retfield[-1].append('░')
+ elif mines >= 3:
+ retfield[-1].append(termcolor.colored(f"{mines}", "red"))
+ elif mines == 2:
+ retfield[-1].append(termcolor.colored(f"{mines}", "yellow"))
+ elif mines == 1:
+ retfield[-1].append(termcolor.colored(f"{mines}", "green"))
+ elif cell == 'M:F':
+ if gamefinnised:
+ retfield[-1].append('S')
+ else:
+ retfield[-1].append('F')
+ elif ':F' in cell:
+ retfield[-1].append('F')
+ elif cell == 'M':
+ if gamefinnised:
+ retfield[-1].append('X')
+ else:
+ retfield[-1].append('█')
+ else:
+ retfield[-1].append('█')
+
+ return retfield
+
+
+clear()
+while gamedata['continue']:
+ print('Y/X| 0123456789\n---|=============')
+ i = 0
+ for row in getuserfield(gamedata['map'], gamefinnised=not(gamedata['continue'])):
+ print(f"{i}|. ", ''.join(row))
+ i += 1
+
+ while True:
+ try:
+ X = int(input('Введите X: '))
+ break
+ except:
+ pass
+ while True:
+ try:
+ Y = int(input('Введите Y: '))
+ break
+ except:
+ pass
+ if input('Введите 0 если хотите поставить флаг: ') == '0':
+ corelib.toggleFlag(gamedata['gamesession'], X, Y)
+ else:
+ corelib.openItem(gamedata['gamesession'], X, Y)
+
+ gamedata = corelib.getGameSession(gamedata['gamesession'])['response']
+ clear()
+
+print('Y/X| 0123456789\n---|=============')
+i = 0
+for row in getuserfield(gamedata['map'], gamefinnised=not(gamedata['continue'])):
+ print(f"{i}|. ", ''.join(row))
+ i += 1
+print('Игра окончена!')
\ No newline at end of file
diff --git a/update.bat b/update.bat
new file mode 100644
index 0000000..0c1dff0
--- /dev/null
+++ b/update.bat
@@ -0,0 +1,3 @@
+git add .
+git commit -m "Up-Date repository"
+git push
\ No newline at end of file