diff --git a/.github/workflows/exebuilder.yml b/.github/workflows/exebuilder.yml index f95f2fb..c5ff7e7 100644 --- a/.github/workflows/exebuilder.yml +++ b/.github/workflows/exebuilder.yml @@ -65,8 +65,10 @@ jobs: # BUILD # ------------------------- - name: Build EXE + shell: bash run: | - python -m PyInstaller --onefile --windowed --name Schach Brett.py + EXE_NAME="Schach_v${{ steps.version.outputs.new_version }}" + python -m PyInstaller --onefile --windowed --add-data "assets;assets" --name "$EXE_NAME" Brett.py # ------------------------- # TAG ERSTELLEN @@ -86,6 +88,6 @@ jobs: with: tag_name: v${{ steps.version.outputs.new_version }} name: Schachspiel v${{ steps.version.outputs.new_version }} - files: dist/Schach.exe + files: dist/Schach_v${{ steps.version.outputs.new_version }}.exe env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index b7faf40..c6b7de1 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ share/python-wheels/ .installed.cfg *.egg MANIFEST +*.exe # PyInstaller # Usually these files are written by a python script from a template diff --git a/Brett.py b/Brett.py index bd6589b..06432e0 100644 --- a/Brett.py +++ b/Brett.py @@ -11,6 +11,7 @@ from Koenig import Koenig from Dialog import Dialog, TextInputDialog from time import time +from resource_path import resource_path class Brett(pygame.sprite.Sprite): ''' @@ -80,7 +81,6 @@ def __setupNetzwerkVars(self): self.__netzVerbundenEvent = threading.Event() self.__netzEmpfangThread:threading.Thread|None = None self.__netzListenerThread:threading.Thread|None = None - self.__netzSucheThread:threading.Thread|None = None self.__spielerName:str = "" self.__meinTeam:int = 0 self.__wendeRemoteZugAn:bool = False @@ -120,7 +120,7 @@ def __zeigeNameDialog(self): Vor.: Die Startdialoggruppe ist initialisiert. Eff.: Der Dialog zur Namenseingabe ist erstellt und aktiv gesetzt. Inform einer weißen Box, welche sich ueber das Schachbrett streckt und die Ueberschrift "Name eingeben" traegt. - Mit den Unterueberschriften "Weiter", welche Interaktionsmoeglichkeiten darstellen im Bezug zur Ueberschrift. + Mit den Unterueberschriften "Zurück" und "Weiter", welche Interaktionsmoeglichkeiten darstellen im Bezug zur Ueberschrift. Texteingaben sind in einem Eingabeberreich dargestellt. Erg.: - ''' @@ -135,7 +135,9 @@ def __zeigeNameDialog(self): onVoidClick=self.__generateImage, posOffset=self.rect.topleft, onSurfaceChange=self.__generateImage, - maxInputLength=24 + maxInputLength=24, + zweiterKnopfText="Zurück", + wennZweiterButton=self.__setupStartDialogs ) self.__startDialogGruppe.empty() self.__startDialogGruppe.add(self.__nameDialog) @@ -144,16 +146,17 @@ def __zeigeNameDialog(self): def __zeigeNetzStatusDialog(self, headline:str): ''' Vor.: -headline- ist ein String und beschreibt die anzuzeigende Ueberschrift. - Eff.: Der Dialog zur Netzwerkinit und Suche ist erstellt und angezeigt. + Eff.: Der Dialog zur Netzwerkinit ist erstellt und angezeigt. Inform einer weißen Box, welche sich ueber das Schachbrett streckt und die Ueberschrift -headline- mittig traegt. - Mit den Unterueberschriften "Erneut suchen", welche eine Interaktionsmoeglichkeit darstellen im Bezug zur Ueberschrift. + Mit den Unterueberschriften zur Anzeige der eigenen IP und zum manuellen Verbinden per IP. Erg.: - ''' + lokaleIp = self.__holeLokaleIp() self.__netzStatusDialog = Dialog( self.rect.width, self.rect.height, (self.rect.width//2, self.rect.height//2), headline, self.rect.height//14, - [["Erneut suchen", self.__starteNetzSuche], ["IP eingeben", self.__zeigeIpDialog]], + [["Eigene IP: " + lokaleIp, None], ["IP eingeben", self.__zeigeIpDialog], ["Zurück", self.__zeigeNameDialog]], self.rect.height//10, 0.7, False, onVoidClick=self.__generateImage, posOffset=self.rect.topleft, @@ -175,7 +178,9 @@ def __zeigeIpDialog(self): onVoidClick=self.__generateImage, posOffset=self.rect.topleft, onSurfaceChange=self.__generateImage, - maxInputLength=15 + maxInputLength=15, + zweiterKnopfText="Zurück", + wennZweiterButton=lambda: self.__zeigeNetzStatusDialog("Warte auf Verbindung") ) self.__startDialogGruppe.empty() self.__startDialogGruppe.add(self.__ipDialog) @@ -257,29 +262,16 @@ def __uebernehmeSpielerName(self, playerName:str): def __starteMultiplayer(self): ''' Vor.: Ein gueltiger Spielername ist gesetzt. - Eff.: Multiplayer ist aktiviert, Listener gestartet und Suche wird gestartet. - Mittels einen bereits in der optik Beschriebenden Dialogfensters ist der Suchstatus mittels der Ueberschrift "Suche im Netzwerk nach Spiel" abzulesen. + Eff.: Multiplayer ist aktiviert, Listener gestartet und die eigene IP wird zur manuellen Verbindungsaufnahme angezeigt. + Mittels einen bereits in der optik Beschriebenden Dialogfensters ist der Status mittels der Ueberschrift "Warte auf Verbindung" abzulesen. Erg.: - ''' self.__netzAktiv = True print("Netzwerkstart auf Host:", socket.gethostname(), "IP:", self.__holeLokaleIp()) - self.__zeigeNetzStatusDialog("Suche im Netzwerk nach Spiel") + self.__zeigeNetzStatusDialog("Warte auf Verbindung") if self.__netzListenerThread == None or not(self.__netzListenerThread.is_alive()): self.__netzListenerThread = threading.Thread(target=self.__listenerWorker, daemon=True) self.__netzListenerThread.start() - self.__starteNetzSuche() - - def __starteNetzSuche(self): - ''' - Vor.: - - Eff.: Ein Suchthread ist gestartet, falls dieser nicht bereits läuft. - Erg.: - - ''' - if self.__netzVerbundenEvent.is_set(): - return - self.__zeigeNetzStatusDialog("Suche im Netzwerk nach Spiel") - self.__netzSucheThread = threading.Thread(target=self.__discoveryWorker, daemon=True) - self.__netzSucheThread.start() def __holeLokaleIp(self)->str: ''' @@ -328,47 +320,6 @@ def __listenerWorker(self): self.__setzeNetzSocket(conn, 1) return - def __discoveryWorker(self): - ''' - Vor.: Netzwerkmodus ist aktiv. - Eff.: Sucht im lokalen Netz nach Gegenstellen und fuehrt ggf. Handshake aus. Bei Fehlern ist der Fehler im Dialogfenster "LAN-Suche fehlgeschlagen" oder "Kein Spiel gefunden, warte auf Anfrage" ablesbar. - Erg.: - - ''' - localIp = self.__holeLokaleIp() - chunks = localIp.split(".") - if len(chunks) != 4: - self.__zeigeNetzStatusDialog("LAN-Suche fehlgeschlagen") - return - prefix = f"{chunks[0]}.{chunks[1]}.{chunks[2]}" - own = int(chunks[3]) - print("Starte Suche in", prefix + ".1-254", "eigene IP-Endung:", own) - for host in range(1, 255): - if not(self.__netzAktiv) or self.__netzVerbundenEvent.is_set(): - return - if host == own: - continue - target = f"{prefix}.{host}" - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - if sock.connect_ex((target, self.__netzPort)) != 0: - sock.close() - continue - print("Port offen auf", target) - sock.sendall(("ASK;" + self.__spielerName + "\n").encode("utf-8")) - print("Gesendet an", target, ": ASK;" + self.__spielerName) - raw = sock.recv(2048) - if len(raw) == 0: - sock.close() - continue - responseText = raw.decode("utf-8").strip() - print("Antwort von", target, ":", responseText) - if responseText.startswith("OK;"): - self.__setzeNetzSocket(sock, 0) - return - sock.close() - if not(self.__netzVerbundenEvent.is_set()): - print("Suche fertig, kein Spiel gefunden") - self.__zeigeNetzStatusDialog("Kein Spiel gefunden, warte auf Anfrage") - def __setzeNetzSocket(self, sock:socket.socket, localTeam:int): ''' Vor.: -sock- ist ein offener Socket, -localTeam- ist eine Team-ID. @@ -381,6 +332,10 @@ def __setzeNetzSocket(self, sock:socket.socket, localTeam:int): return self.__netzSock = sock self.__meinTeam = localTeam + if self.__meinTeam == 0: + self.setRotation(180) + else: + self.setRotation(0) self.__netzVerbundenEvent.set() print("Verbindung hergestellt. Eigenes Team:", localTeam) if self.__modusDialog != None: @@ -548,7 +503,7 @@ def setupDialogGroup(self): self.rect.width, self.rect.height, (self.rect.width//2, self.rect.height//2), "Was möchtest du tun?", self.rect.height//8, - [["Neues Spiel!", self.restartGame]], + [["Neues Spiel!", self.restartGame], ["Zurück", self.__resignDialogAusblenden]], self.rect.height//5, 0.4, True, onVoidClick=self.__generateImage, posOffset=self.rect.topleft, @@ -556,6 +511,15 @@ def setupDialogGroup(self): ) self.__DialogGroup.add(self.__resignDialog) + def __resignDialogAusblenden(self): + ''' + Vor.: Der Aufgabedialog ist initialisiert. + Eff.: Der Aufgabedialog ist ausgeblendet und das Brettbild aktualisiert. + Erg.: - + ''' + self.__resignDialog.hideSurface() + self.__generateImage() + def __reset_game_state(self): ''' Vor.: - @@ -1725,7 +1689,7 @@ def getFieldByCords(self, pos:tuple[int, int])->Feld|None: if __name__ == "__main__": pygame.init() - icon = pygame.image.load("assets/graphics/icon.png") + icon = pygame.image.load(resource_path("assets/graphics/icon.png")) width = 800 height = width screen = pygame.display.set_mode((width, height)) @@ -1764,4 +1728,5 @@ def getFieldByCords(self, pos:tuple[int, int])->Feld|None: TestBrettGroup.draw(screen) TestBrettGroup.update() pygame.display.update() - clock.tick(60) \ No newline at end of file + + clock.tick(60) diff --git a/Dialog.py b/Dialog.py index 895dba7..e5af114 100644 --- a/Dialog.py +++ b/Dialog.py @@ -165,7 +165,7 @@ def handleLeftClick(self, pos:tuple[int, int]): self.hideSurface() class TextInputDialog(pygame.sprite.Sprite): - def __init__(self, DialogWidth:int, DialogHeight:int, centerPosition:tuple[int], headline:str, headlineSize:int, inputSize:int, buttonText:str, buttonSize:int, closeable:bool, onSubmit:Callable|None=None, onVoidClick:Callable|None=None, posOffset:tuple[int, int]=(0,0), onSurfaceChange:Callable=None, maxInputLength:int=24): + def __init__(self, DialogWidth:int, DialogHeight:int, centerPosition:tuple[int], headline:str, headlineSize:int, inputSize:int, buttonText:str, buttonSize:int, closeable:bool, onSubmit:Callable|None=None, onVoidClick:Callable|None=None, posOffset:tuple[int, int]=(0,0), onSurfaceChange:Callable=None, maxInputLength:int=24, zweiterKnopfText:str|None=None, wennZweiterButton:Callable|None=None): super().__init__() self.__initPhase = True self.__width:int = DialogWidth @@ -182,6 +182,8 @@ def __init__(self, DialogWidth:int, DialogHeight:int, centerPosition:tuple[int], self.__posOffset = posOffset self.__onSurfaceChange = onSurfaceChange self.__maxInputLength:int = maxInputLength + self.__secondaryButtonText:str|None = zweiterKnopfText + self.__wennZweiterButton:Callable|None = wennZweiterButton self.__isShown = True self.__eingabeWert:str = "" self.__cursorSichtbar:bool = True @@ -240,9 +242,19 @@ def makeSurface(self): buttonFont = pygame.font.Font(None, self.__buttonSize) self.__buttonSurface = buttonFont.render(self.__buttonText, False, "black").convert() - self.__buttonRect = self.__buttonSurface.get_rect(center=(self.__width//2, int(self.__height*0.78))) + buttonCenterY = int(self.__height*0.78) + if self.__secondaryButtonText == None: + self.__buttonRect = self.__buttonSurface.get_rect(center=(self.__width//2, buttonCenterY)) + else: + self.__buttonRect = self.__buttonSurface.get_rect(center=(int(self.__width*0.68), buttonCenterY)) self.image.blit(self.__buttonSurface, self.__buttonRect) + self.__secondaryButtonRect = None + if self.__secondaryButtonText != None: + self.__secondaryButtonSurface = buttonFont.render(self.__secondaryButtonText, False, "black").convert() + self.__secondaryButtonRect = self.__secondaryButtonSurface.get_rect(center=(int(self.__width*0.32), buttonCenterY)) + self.image.blit(self.__secondaryButtonSurface, self.__secondaryButtonRect) + if not(self.__initPhase): self.__CallOnSurfaceChange() @@ -260,6 +272,10 @@ def handleLeftClick(self, pos:tuple[int, int]): return localPos = (pos[0] - self.rect.x - self.__posOffset[0], pos[1] - self.rect.y - self.__posOffset[1]) didNoAction = True + if self.__secondaryButtonRect != None and self.__secondaryButtonRect.collidepoint(localPos): + if self.__wennZweiterButton != None: + self.__wennZweiterButton() + didNoAction = False if self.__buttonRect.collidepoint(localPos): if self.__onSubmit != None: self.__onSubmit(self.__eingabeWert) @@ -273,6 +289,10 @@ def handleLeftClick(self, pos:tuple[int, int]): def handleKeyDown(self, event:pygame.event.Event): if not(self.__isShown): return + if event.key == pygame.K_ESCAPE: + if self.__wennZweiterButton != None: + self.__wennZweiterButton() + return if event.key == pygame.K_RETURN: if self.__onSubmit != None: self.__onSubmit(self.__eingabeWert) diff --git a/FigurBuilder.py b/FigurBuilder.py index f6c0204..5850b4f 100644 --- a/FigurBuilder.py +++ b/FigurBuilder.py @@ -1,6 +1,7 @@ import pygame from sys import exit from typing import Callable +from resource_path import resource_path class FigurBuilder(pygame.sprite.Sprite): ''' @@ -28,7 +29,7 @@ def __init__(self, image:str, size:int, field_length:int, field_count:int, field self.__field_count:int = field_count self.__fieldLabelStartLetter:str = fieldLabelStartLetter - self.image:pygame.surface.Surface = pygame.image.load(self.__imagePath).convert_alpha() + self.image:pygame.surface.Surface = pygame.image.load(resource_path(self.__imagePath)).convert_alpha() self.image:pygame.surface.Surface = pygame.transform.scale(self.image, (size, size)) self.rect:pygame.rect.Rect = self.image.get_rect(center = self.__centerPos) diff --git a/alleklassen.dot b/alleklassen.dot new file mode 100644 index 0000000..2182ef0 --- /dev/null +++ b/alleklassen.dot @@ -0,0 +1,37 @@ +digraph "classes_neu" { +rankdir=BT +charset="utf-8" +"Bauer.Bauer" [color="black", fontcolor="black", label=<{Bauer|__didDoubleWalkInTurns : list
__mustKill : bool
|__init__(image: str, size: int, field_length: int, field_count: int, fieldLabelStartLetter: str, teamID: int, mustKill: bool)
didDoubleWalk(TurnNumber: int): None
getMaybePossibleTurns(originFieldLabel: str): list[dict]
hasDidDoubleWalkInTurn(testTurnNumber: int): bool
}>, shape="record", style="solid"]; +"Brett.Brett" [color="black", fontcolor="black", label=<{Brett|__DialogGroup
__FigureScale : float
__PawnPromotes : list
__blackBishop
__blackKing
__blackKnight
__blackQueen
__blackTower
__cursor : NoneType
__edge_length : int
__eventMode : str \| None
__field_color_1 : str
__field_color_2 : str
__field_label_start_letter : str
__field_length : int
__fields : dict[str:Feld]
__fieldsGroup
__fields_count : int
__ipDialog : TextInputDialog \| None
__meinTeam : int
__modusDialog : Dialog \| None
__nameDialog : TextInputDialog \| None
__netzAktiv : bool
__netzBuffer : str
__netzEmpfangThread : threading.Thread \| None
__netzListenerThread : threading.Thread \| None
__netzPort : int
__netzSock : socket.socket \| None
__netzStatusDialog : Dialog \| None
__netzVerbundenEvent : Event
__onTurnTeam : int
__ready : bool
__resignDialog
__rotation : int
__running : bool
__spielerName : str
__startDialogGruppe
__turnNumber : int
__wendeRemoteZugAn : bool
__whiteBishop
__whiteKing
__whiteKnight
__whiteQueen
__whiteTower
image
rect
|SetupTurnVars()
__CheckIfIsNotAFeldInstance(testObject: object): bool
__SpitNegativePoints(Line: list[dict], SplitNumberIndex: int): list[list, list]
__buildPawnRow(RowNumber: int, scale: float, texturePath: str, teamID: int): None
__checkCastlingConditions(KingField: Feld, TargetField: Feld): bool
__chooseFigureEvent(clickedField: Feld): bool
__clearAllFieldHighlights(): None
__correctFieldPositions(): None
__createFields(): dict
__createFieldsGroup(): pygame.sprite.Group
__cutLineAtWalkingThroughFigures(Line: list[dict], startField: Feld): list[dict] \| list
__direktConnectWorker(targetIp: str)
__doPromote(Team0Figure, Team1Figure, promotionName: str)
__finishTurn()
__generateImage(): None
__getCheckedTeams(): list[int]
__getClickPosByLabel(fieldLabel: str): tuple[int, int] \| None
__getDangerFieldsToTheField(testForField: Feld, TeamID: int \| None): list[Feld]
__getDangerFieldsWhenMove(targetField: Feld, OriginField: Feld): list[Feld]
__getFieldLabelsPositionIDs(FieldLabel: str): list[int, int]
__getFieldPositionByName(field_name: str): tuple[int, int]
__getFieldsBetweenHorizontalVerticalOnly(startingField: Feld, targetField: Feld): list[Feld]
__getFieldsGroup(): pygame.sprite.Group
__getFieldsWithKings(): list[Feld]
__getKingFieldsInDanger(): list[Feld]
__getLabelByPositionIDs(PositionIDs: list[int, int]): str
__getMatchingTurnData(startField: Feld, targetField: Feld): dict \| None
__getOnlyPointsList(TurnsDatas: list[dict]): list[tuple]
__getOnlyTurnDataWithValidFields(turnsData: list[dict]): list[dict]
__getPointFromDict(DataDict: dict): tuple
__getTurnDataWithoutWalkThroughFigures(relativeMaybePossibleTurnsData: list[dict], startField: Feld): list \| list[dict]
__getTurnsNotKillingMatesFromTurnData(turnsData: list[dict], TeamID: int): list[dict]
__holeLokaleIp(): str
__init__(edge_length: int, topLeftCorner: tuple[int, int], field_color1: str, field_color2: str, rotation: int)
__istIPv4Gueltig(ipText: str): bool
__listenerWorker()
__markAllPosibleFields(FigureFieldLabel: str): None
__promoteBishop()
__promoteKnight()
__promoteQueen()
__promoteTower()
__receiverWorker()
__resetCursorAndSetEventMode(eventMode: str)
__reset_game_state()
__resignDialogAusblenden()
__reverseFirstPart(Line: list): tuple
__rotatePoint90degree(point: tuple[int, int]): tuple[int, int]
__sendeNetzMessage(text: str)
__setFigureEvent(clickedField: Feld): None
__setupBrett(): None
__setupNetzwerkVars()
__setupStartDialogs()
__setzeNetzSocket(sock: socket.socket, localTeam: int)
__setzeRemotePromo(fieldLabel: str, pieceName: str)
__setzeRemoteZug(startLabel: str, targetLabel: str)
__sortToDestination(Line: list[dict], sortIndex: int): list[list[dict]]
__starteMultiplayer()
__starteNetzEmpfang()
__switchToOtherPlayer(): None
__uebernehmeSpielerName(playerName: str)
__verbindeMitIpText(ipText: str)
__waehleSingleplayer()
__zeigeIpDialog()
__zeigeNameDialog()
__zeigeNetzStatusDialog(headline: str)
checkIfMate(): list[int]
checkIfTeamCanMove(team: int)
getFieldByCords(pos: tuple[int, int]): Feld \| None
getFieldRow(RowNumber: int): list[Feld]
getPossibleTurnFields(Field: Feld, ignoreChecksOrAnxiety: bool, ignoreBuildingChecks: bool, ignoreCastling: bool): list[Feld]
getPossibleTurnFieldsFullData(startingPointField: Feld, ignoreChecksOrAnxiety: bool, ignoreBuildingChecks: bool, ignoreCastling: bool): list[dict]
getRelativeField(fieldLabel: str, relativeField: tuple[int, int]): Feld \| None
getRotation(): int
handleKeyDownEvent(event: pygame.event.Event): None
handleLeftClickEvent(pos: tuple[int, int]): None
handleRightClickEvent(pos: tuple[int, int]): None
restartGame()
setRotation(rotation: int): None
setupDialogGroup()
start(): None
update(): None
}>, shape="record", style="solid"]; +"Dame.Dame" [color="black", fontcolor="black", label=<{Dame|__mustKill : bool
|__init__(image: str, size: int, field_length: int, field_count: int, fieldLabelStartLetter: str, teamID: int, mustKill: bool)
getMaybePossibleTurns(originFieldLabel: str): list[dict]
}>, shape="record", style="solid"]; +"Dialog.Dialog" [color="black", fontcolor="black", label=<{Dialog|__answerDistanceSize : int
__answerSize : int
__answers : list[list[str, Callable]]
__answersDataWithSurface : list[dict]
__centerPosition : tuple[int]
__closeable : bool
__headline : str
__headlineSize : int
__height : int
__initPhase : bool
__isShown : bool
__onSurfaceChange : Optional[Callable]
__onVoidClick : Callable \| None
__posOffset : tuple[int, int]
__width : int
image
questionTextSurface
rect
|__CallOnSurfaceChange()
__init__(DialogWidth: int, DialogHeight: int, centerPosition: tuple[int, int], headline: str, headlineSize: int, answers: list[list[str, Callable]], answerSize: int, answerDistanceSize: int, closeable: bool, onVoidClick: Callable \| None, posOffset: tuple[int, int], onSurfaceChange: Optional[Callable])
createSelfAnswersSurfaceData()
getIfShown(): bool
handleLeftClick(pos: tuple[int, int])
hideSurface()
makeSurface()
showSurface()
}>, shape="record", style="solid"]; +"Feld.Feld" [color="black", fontcolor="black", label=<{Feld|__FigureGroup
__effectKeyHighlight : str
__effects : list
__figure : Optional[None \| Springer \| Turm \| Bauer \| Laeufer \| Dame \| Koenig]
__label : str
__size : tuple[int, int]
color : str
image
rect
|__drawFieldSurface(): None
__getFigureGroup(): pygame.sprite.GroupSingle
__init__(size: tuple[int, int], topLeftCorner: tuple[int, int], color: str, label: str)
addFieldHighlight(HighlightType: str): None
clearFieldHighlights(): None
getFigure(): None \| Springer \| Turm \| Bauer \| Laeufer \| Dame \| Koenig
getLabel(): str
getRect(): pygame.rect.Rect
removeFieldHighlight(HighlightType: str): None
setFieldPosition(topLeftCorner: tuple[int, int]): None
setFigure(Figure: None \| Springer \| Turm \| Bauer \| Laeufer \| Dame \| Koenig)
update(): None
}>, shape="record", style="solid"]; +"FigurBuilder.FigurBuilder" [color="black", fontcolor="black", label=<{FigurBuilder|__KillMates : bool
__canJump : bool
__centerPos : tuple[int, int]
__fieldLabelStartLetter : str
__field_count : int
__field_length : int
__hasKingRole : bool
__imagePath : str
__movedAmount : int
__team : int
image
rect
|__getIsFieldLabelValid(testFieldlabel: str)
__init__(image: str, size: int, field_length: int, field_count: int, fieldLabelStartLetter: str, teamID: int, canJump: bool, KillMates: bool, hasKingRole: bool)
convertRelativePointToFieldLabel(originFieldLabel: str, RelativePoint: tuple[int, int]): str \| None
getCanJump(): bool
getCanKillMates(): bool
getHasMoved(): bool
getKingRole(): bool
getMovedAmount(): int
getNewTurnsListWithAddingRelative(originFieldLabel: str, oldZugList: list, RelativePoint: tuple[int, int], onlyOnKill: bool, canKill: bool, hasAnxiety: bool, specialMoveLabel: str \| None, needFigureOnField: str \| None, needFigureType: type \| None, allowNeededFigureHasTurned: bool \| None, endPointNeededFigure: str \| None, onDoneTurnCall: Callable \| None, killMaybeFigureType: type \| None, killMaybeFigureField: str \| None, killMaybeFigureMustHadDoubleWalkLastTurn: bool): list[dict]
getTeam(): int
moved()
setFieldCount(field_count: int): None
setFieldLabelStartLetter(Letter: str): None
setKingRole(kingRole: bool): None
undoMovedCounterByOne()
}>, shape="record", style="solid"]; +"Koenig.Koenig" [color="black", fontcolor="black", label=<{Koenig|__canKill : bool
__hasAnxiety : bool
__mustKill : bool
|__init__(image: str, size: int, field_length: int, field_count: int, fieldLabelStartLetter: str, teamID: int, mustKill: bool)
getMaybePossibleTurns(originFieldLabel: str): list[dict]
}>, shape="record", style="solid"]; +"Laeufer.Laeufer" [color="black", fontcolor="black", label=<{Laeufer|__mustKill : bool
|__init__(image: str, size: int, field_length: int, field_count: int, fieldLabelStartLetter: str, teamID: int, mustKill: bool)
getMaybePossibleTurns(originFieldLabel: str): list[dict]
}>, shape="record", style="solid"]; +"Springer.Springer" [color="black", fontcolor="black", label=<{Springer|__SchrittBreite : int
__SchrittLaenge : int
__mustKill : bool
|__init__(image: str, size: int, field_length: int, field_count: int, fieldLabelStartLetter: str, teamID: int, mustKill: bool)
getMaybePossibleTurns(originFieldLabel: str): list[dict]
}>, shape="record", style="solid"]; +"Dialog.TextInputDialog" [color="black", fontcolor="black", label=<{TextInputDialog|__buttonRect
__buttonSize : int
__buttonSurface
__buttonText : str
__centerPosition : tuple[int]
__closeable : bool
__cursorSichtbar : bool
__eingabeWert : str
__headline : str
__headlineSize : int
__height : int
__initPhase : bool
__inputSize : int
__isShown : bool
__letzterCursorBlink
__maxInputLength : int
__onSubmit : Callable \| None
__onSurfaceChange : Optional[Callable]
__onVoidClick : Callable \| None
__posOffset : tuple[int, int]
__secondaryButtonRect : NoneType
__secondaryButtonSurface
__secondaryButtonText : str \| None
__wennZweiterButton : Callable \| None
__width : int
image
rect
|__CallOnSurfaceChange()
__init__(DialogWidth: int, DialogHeight: int, centerPosition: tuple[int], headline: str, headlineSize: int, inputSize: int, buttonText: str, buttonSize: int, closeable: bool, onSubmit: Callable \| None, onVoidClick: Callable \| None, posOffset: tuple[int, int], onSurfaceChange: Optional[Callable], maxInputLength: int, zweiterKnopfText: str \| None, wennZweiterButton: Callable \| None)
clearValue()
getIfShown()
getValue(): str
handleKeyDown(event: pygame.event.Event)
handleLeftClick(pos: tuple[int, int])
hideSurface()
makeSurface()
setHeadline(headline: str)
showSurface()
update()
}>, shape="record", style="solid"]; +"Turm.Turm" [color="black", fontcolor="black", label=<{Turm|__mustKill : bool
|__init__(image: str, size: int, field_length: int, field_count: int, fieldLabelStartLetter: str, teamID: int, mustKill: bool)
getMaybePossibleTurns(originFieldLabel: str): list[dict]
}>, shape="record", style="solid"]; +"Bauer.Bauer" -> "FigurBuilder.FigurBuilder" [arrowhead="empty", arrowtail="none"]; +"Dame.Dame" -> "FigurBuilder.FigurBuilder" [arrowhead="empty", arrowtail="none"]; +"Koenig.Koenig" -> "FigurBuilder.FigurBuilder" [arrowhead="empty", arrowtail="none"]; +"Laeufer.Laeufer" -> "FigurBuilder.FigurBuilder" [arrowhead="empty", arrowtail="none"]; +"Springer.Springer" -> "FigurBuilder.FigurBuilder" [arrowhead="empty", arrowtail="none"]; +"Turm.Turm" -> "FigurBuilder.FigurBuilder" [arrowhead="empty", arrowtail="none"]; +"Dame.Dame" -> "Brett.Brett" [arrowhead="diamond", arrowtail="none", fontcolor="green", label="__blackQueen", style="solid"]; +"Dame.Dame" -> "Brett.Brett" [arrowhead="diamond", arrowtail="none", fontcolor="green", label="__whiteQueen", style="solid"]; +"Dialog.Dialog" -> "Brett.Brett" [arrowhead="diamond", arrowtail="none", fontcolor="green", label="__modusDialog", style="solid"]; +"Dialog.Dialog" -> "Brett.Brett" [arrowhead="diamond", arrowtail="none", fontcolor="green", label="__netzStatusDialog", style="solid"]; +"Dialog.Dialog" -> "Brett.Brett" [arrowhead="diamond", arrowtail="none", fontcolor="green", label="__resignDialog", style="solid"]; +"Dialog.TextInputDialog" -> "Brett.Brett" [arrowhead="diamond", arrowtail="none", fontcolor="green", label="__nameDialog", style="solid"]; +"Dialog.TextInputDialog" -> "Brett.Brett" [arrowhead="diamond", arrowtail="none", fontcolor="green", label="__ipDialog", style="solid"]; +"Koenig.Koenig" -> "Brett.Brett" [arrowhead="diamond", arrowtail="none", fontcolor="green", label="__blackKing", style="solid"]; +"Koenig.Koenig" -> "Brett.Brett" [arrowhead="diamond", arrowtail="none", fontcolor="green", label="__whiteKing", style="solid"]; +"Laeufer.Laeufer" -> "Brett.Brett" [arrowhead="diamond", arrowtail="none", fontcolor="green", label="__blackBishop", style="solid"]; +"Laeufer.Laeufer" -> "Brett.Brett" [arrowhead="diamond", arrowtail="none", fontcolor="green", label="__whiteBishop", style="solid"]; +"Springer.Springer" -> "Brett.Brett" [arrowhead="diamond", arrowtail="none", fontcolor="green", label="__blackKnight", style="solid"]; +"Springer.Springer" -> "Brett.Brett" [arrowhead="diamond", arrowtail="none", fontcolor="green", label="__whiteKnight", style="solid"]; +"Turm.Turm" -> "Brett.Brett" [arrowhead="diamond", arrowtail="none", fontcolor="green", label="__blackTower", style="solid"]; +"Turm.Turm" -> "Brett.Brett" [arrowhead="diamond", arrowtail="none", fontcolor="green", label="__whiteTower", style="solid"]; +"Feld.Feld" -> "Brett.Brett" [arrowhead="odiamond", arrowtail="none", fontcolor="green", label="__cursor", style="solid"]; +} diff --git a/alleklassen.svg b/alleklassen.svg new file mode 100644 index 0000000..ecd406b --- /dev/null +++ b/alleklassen.svg @@ -0,0 +1,514 @@ + + + + + + +classes_neu + + + +Bauer.Bauer + +Bauer + +__didDoubleWalkInTurns : list +__mustKill : bool + +__init__(image: str, size: int, field_length: int, field_count: int, fieldLabelStartLetter: str, teamID: int, mustKill: bool) +didDoubleWalk(TurnNumber: int): None +getMaybePossibleTurns(originFieldLabel: str): list[dict] +hasDidDoubleWalkInTurn(testTurnNumber: int): bool + + + +FigurBuilder.FigurBuilder + +FigurBuilder + +__KillMates : bool +__canJump : bool +__centerPos : tuple[int, int] +__fieldLabelStartLetter : str +__field_count : int +__field_length : int +__hasKingRole : bool +__imagePath : str +__movedAmount : int +__team : int +image +rect + +__getIsFieldLabelValid(testFieldlabel: str) +__init__(image: str, size: int, field_length: int, field_count: int, fieldLabelStartLetter: str, teamID: int, canJump: bool, KillMates: bool, hasKingRole: bool) +convertRelativePointToFieldLabel(originFieldLabel: str, RelativePoint: tuple[int, int]): str | None +getCanJump(): bool +getCanKillMates(): bool +getHasMoved(): bool +getKingRole(): bool +getMovedAmount(): int +getNewTurnsListWithAddingRelative(originFieldLabel: str, oldZugList: list, RelativePoint: tuple[int, int], onlyOnKill: bool, canKill: bool, hasAnxiety: bool, specialMoveLabel: str | None, needFigureOnField: str | None, needFigureType: type | None, allowNeededFigureHasTurned: bool | None, endPointNeededFigure: str | None, onDoneTurnCall: Callable | None, killMaybeFigureType: type | None, killMaybeFigureField: str | None, killMaybeFigureMustHadDoubleWalkLastTurn: bool): list[dict] +getTeam(): int +moved() +setFieldCount(field_count: int): None +setFieldLabelStartLetter(Letter: str): None +setKingRole(kingRole: bool): None +undoMovedCounterByOne() + + + +Bauer.Bauer->FigurBuilder.FigurBuilder + + + + + +Brett.Brett + +Brett + +__DialogGroup +__FigureScale : float +__PawnPromotes : list +__blackBishop +__blackKing +__blackKnight +__blackQueen +__blackTower +__cursor : NoneType +__edge_length : int +__eventMode : str | None +__field_color_1 : str +__field_color_2 : str +__field_label_start_letter : str +__field_length : int +__fields : dict[str:Feld] +__fieldsGroup +__fields_count : int +__ipDialog : TextInputDialog | None +__meinTeam : int +__modusDialog : Dialog | None +__nameDialog : TextInputDialog | None +__netzAktiv : bool +__netzBuffer : str +__netzEmpfangThread : threading.Thread | None +__netzListenerThread : threading.Thread | None +__netzPort : int +__netzSock : socket.socket | None +__netzStatusDialog : Dialog | None +__netzVerbundenEvent : Event +__onTurnTeam : int +__ready : bool +__resignDialog +__rotation : int +__running : bool +__spielerName : str +__startDialogGruppe +__turnNumber : int +__wendeRemoteZugAn : bool +__whiteBishop +__whiteKing +__whiteKnight +__whiteQueen +__whiteTower +image +rect + +SetupTurnVars() +__CheckIfIsNotAFeldInstance(testObject: object): bool +__SpitNegativePoints(Line: list[dict], SplitNumberIndex: int): list[list, list] +__buildPawnRow(RowNumber: int, scale: float, texturePath: str, teamID: int): None +__checkCastlingConditions(KingField: Feld, TargetField: Feld): bool +__chooseFigureEvent(clickedField: Feld): bool +__clearAllFieldHighlights(): None +__correctFieldPositions(): None +__createFields(): dict +__createFieldsGroup(): pygame.sprite.Group +__cutLineAtWalkingThroughFigures(Line: list[dict], startField: Feld): list[dict] | list +__direktConnectWorker(targetIp: str) +__doPromote(Team0Figure, Team1Figure, promotionName: str) +__finishTurn() +__generateImage(): None +__getCheckedTeams(): list[int] +__getClickPosByLabel(fieldLabel: str): tuple[int, int] | None +__getDangerFieldsToTheField(testForField: Feld, TeamID: int | None): list[Feld] +__getDangerFieldsWhenMove(targetField: Feld, OriginField: Feld): list[Feld] +__getFieldLabelsPositionIDs(FieldLabel: str): list[int, int] +__getFieldPositionByName(field_name: str): tuple[int, int] +__getFieldsBetweenHorizontalVerticalOnly(startingField: Feld, targetField: Feld): list[Feld] +__getFieldsGroup(): pygame.sprite.Group +__getFieldsWithKings(): list[Feld] +__getKingFieldsInDanger(): list[Feld] +__getLabelByPositionIDs(PositionIDs: list[int, int]): str +__getMatchingTurnData(startField: Feld, targetField: Feld): dict | None +__getOnlyPointsList(TurnsDatas: list[dict]): list[tuple] +__getOnlyTurnDataWithValidFields(turnsData: list[dict]): list[dict] +__getPointFromDict(DataDict: dict): tuple +__getTurnDataWithoutWalkThroughFigures(relativeMaybePossibleTurnsData: list[dict], startField: Feld): list | list[dict] +__getTurnsNotKillingMatesFromTurnData(turnsData: list[dict], TeamID: int): list[dict] +__holeLokaleIp(): str +__init__(edge_length: int, topLeftCorner: tuple[int, int], field_color1: str, field_color2: str, rotation: int) +__istIPv4Gueltig(ipText: str): bool +__listenerWorker() +__markAllPosibleFields(FigureFieldLabel: str): None +__promoteBishop() +__promoteKnight() +__promoteQueen() +__promoteTower() +__receiverWorker() +__resetCursorAndSetEventMode(eventMode: str) +__reset_game_state() +__resignDialogAusblenden() +__reverseFirstPart(Line: list): tuple +__rotatePoint90degree(point: tuple[int, int]): tuple[int, int] +__sendeNetzMessage(text: str) +__setFigureEvent(clickedField: Feld): None +__setupBrett(): None +__setupNetzwerkVars() +__setupStartDialogs() +__setzeNetzSocket(sock: socket.socket, localTeam: int) +__setzeRemotePromo(fieldLabel: str, pieceName: str) +__setzeRemoteZug(startLabel: str, targetLabel: str) +__sortToDestination(Line: list[dict], sortIndex: int): list[list[dict]] +__starteMultiplayer() +__starteNetzEmpfang() +__switchToOtherPlayer(): None +__uebernehmeSpielerName(playerName: str) +__verbindeMitIpText(ipText: str) +__waehleSingleplayer() +__zeigeIpDialog() +__zeigeNameDialog() +__zeigeNetzStatusDialog(headline: str) +checkIfMate(): list[int] +checkIfTeamCanMove(team: int) +getFieldByCords(pos: tuple[int, int]): Feld | None +getFieldRow(RowNumber: int): list[Feld] +getPossibleTurnFields(Field: Feld, ignoreChecksOrAnxiety: bool, ignoreBuildingChecks: bool, ignoreCastling: bool): list[Feld] +getPossibleTurnFieldsFullData(startingPointField: Feld, ignoreChecksOrAnxiety: bool, ignoreBuildingChecks: bool, ignoreCastling: bool): list[dict] +getRelativeField(fieldLabel: str, relativeField: tuple[int, int]): Feld | None +getRotation(): int +handleKeyDownEvent(event: pygame.event.Event): None +handleLeftClickEvent(pos: tuple[int, int]): None +handleRightClickEvent(pos: tuple[int, int]): None +restartGame() +setRotation(rotation: int): None +setupDialogGroup() +start(): None +update(): None + + + +Dame.Dame + +Dame + +__mustKill : bool + +__init__(image: str, size: int, field_length: int, field_count: int, fieldLabelStartLetter: str, teamID: int, mustKill: bool) +getMaybePossibleTurns(originFieldLabel: str): list[dict] + + + +Dame.Dame->Brett.Brett + + +__blackQueen + + + +Dame.Dame->Brett.Brett + + +__whiteQueen + + + +Dame.Dame->FigurBuilder.FigurBuilder + + + + + +Dialog.Dialog + +Dialog + +__answerDistanceSize : int +__answerSize : int +__answers : list[list[str, Callable]] +__answersDataWithSurface : list[dict] +__centerPosition : tuple[int] +__closeable : bool +__headline : str +__headlineSize : int +__height : int +__initPhase : bool +__isShown : bool +__onSurfaceChange : Optional[Callable] +__onVoidClick : Callable | None +__posOffset : tuple[int, int] +__width : int +image +questionTextSurface +rect + +__CallOnSurfaceChange() +__init__(DialogWidth: int, DialogHeight: int, centerPosition: tuple[int, int], headline: str, headlineSize: int, answers: list[list[str, Callable]], answerSize: int, answerDistanceSize: int, closeable: bool, onVoidClick: Callable | None, posOffset: tuple[int, int], onSurfaceChange: Optional[Callable]) +createSelfAnswersSurfaceData() +getIfShown(): bool +handleLeftClick(pos: tuple[int, int]) +hideSurface() +makeSurface() +showSurface() + + + +Dialog.Dialog->Brett.Brett + + +__modusDialog + + + +Dialog.Dialog->Brett.Brett + + +__netzStatusDialog + + + +Dialog.Dialog->Brett.Brett + + +__resignDialog + + + +Feld.Feld + +Feld + +__FigureGroup +__effectKeyHighlight : str +__effects : list +__figure : Optional[None | Springer | Turm | Bauer | Laeufer | Dame | Koenig] +__label : str +__size : tuple[int, int] +color : str +image +rect + +__drawFieldSurface(): None +__getFigureGroup(): pygame.sprite.GroupSingle +__init__(size: tuple[int, int], topLeftCorner: tuple[int, int], color: str, label: str) +addFieldHighlight(HighlightType: str): None +clearFieldHighlights(): None +getFigure(): None | Springer | Turm | Bauer | Laeufer | Dame | Koenig +getLabel(): str +getRect(): pygame.rect.Rect +removeFieldHighlight(HighlightType: str): None +setFieldPosition(topLeftCorner: tuple[int, int]): None +setFigure(Figure: None | Springer | Turm | Bauer | Laeufer | Dame | Koenig) +update(): None + + + +Feld.Feld->Brett.Brett + + +__cursor + + + +Koenig.Koenig + +Koenig + +__canKill : bool +__hasAnxiety : bool +__mustKill : bool + +__init__(image: str, size: int, field_length: int, field_count: int, fieldLabelStartLetter: str, teamID: int, mustKill: bool) +getMaybePossibleTurns(originFieldLabel: str): list[dict] + + + +Koenig.Koenig->Brett.Brett + + +__blackKing + + + +Koenig.Koenig->Brett.Brett + + +__whiteKing + + + +Koenig.Koenig->FigurBuilder.FigurBuilder + + + + + +Laeufer.Laeufer + +Laeufer + +__mustKill : bool + +__init__(image: str, size: int, field_length: int, field_count: int, fieldLabelStartLetter: str, teamID: int, mustKill: bool) +getMaybePossibleTurns(originFieldLabel: str): list[dict] + + + +Laeufer.Laeufer->Brett.Brett + + +__blackBishop + + + +Laeufer.Laeufer->Brett.Brett + + +__whiteBishop + + + +Laeufer.Laeufer->FigurBuilder.FigurBuilder + + + + + +Springer.Springer + +Springer + +__SchrittBreite : int +__SchrittLaenge : int +__mustKill : bool + +__init__(image: str, size: int, field_length: int, field_count: int, fieldLabelStartLetter: str, teamID: int, mustKill: bool) +getMaybePossibleTurns(originFieldLabel: str): list[dict] + + + +Springer.Springer->Brett.Brett + + +__blackKnight + + + +Springer.Springer->Brett.Brett + + +__whiteKnight + + + +Springer.Springer->FigurBuilder.FigurBuilder + + + + + +Dialog.TextInputDialog + +TextInputDialog + +__buttonRect +__buttonSize : int +__buttonSurface +__buttonText : str +__centerPosition : tuple[int] +__closeable : bool +__cursorSichtbar : bool +__eingabeWert : str +__headline : str +__headlineSize : int +__height : int +__initPhase : bool +__inputSize : int +__isShown : bool +__letzterCursorBlink +__maxInputLength : int +__onSubmit : Callable | None +__onSurfaceChange : Optional[Callable] +__onVoidClick : Callable | None +__posOffset : tuple[int, int] +__secondaryButtonRect : NoneType +__secondaryButtonSurface +__secondaryButtonText : str | None +__wennZweiterButton : Callable | None +__width : int +image +rect + +__CallOnSurfaceChange() +__init__(DialogWidth: int, DialogHeight: int, centerPosition: tuple[int], headline: str, headlineSize: int, inputSize: int, buttonText: str, buttonSize: int, closeable: bool, onSubmit: Callable | None, onVoidClick: Callable | None, posOffset: tuple[int, int], onSurfaceChange: Optional[Callable], maxInputLength: int, zweiterKnopfText: str | None, wennZweiterButton: Callable | None) +clearValue() +getIfShown() +getValue(): str +handleKeyDown(event: pygame.event.Event) +handleLeftClick(pos: tuple[int, int]) +hideSurface() +makeSurface() +setHeadline(headline: str) +showSurface() +update() + + + +Dialog.TextInputDialog->Brett.Brett + + +__nameDialog + + + +Dialog.TextInputDialog->Brett.Brett + + +__ipDialog + + + +Turm.Turm + +Turm + +__mustKill : bool + +__init__(image: str, size: int, field_length: int, field_count: int, fieldLabelStartLetter: str, teamID: int, mustKill: bool) +getMaybePossibleTurns(originFieldLabel: str): list[dict] + + + +Turm.Turm->Brett.Brett + + +__blackTower + + + +Turm.Turm->Brett.Brett + + +__whiteTower + + + +Turm.Turm->FigurBuilder.FigurBuilder + + + + + diff --git a/resource_path.py b/resource_path.py new file mode 100644 index 0000000..ccbcbf5 --- /dev/null +++ b/resource_path.py @@ -0,0 +1,15 @@ +import os +import sys + + +def resource_path(relative_path:str)->str: + ''' + Vor.: -relative_path- ist ein relativer Pfad innerhalb des Projekts. + Eff.: - + Erg.: Der zur Laufzeit gueltige absolute Pfad ist geliefert, sowohl im Projektordner als auch in einer PyInstaller-Exe. + ''' + if hasattr(sys, "_MEIPASS"): + base_path = sys._MEIPASS + else: + base_path = os.path.dirname(os.path.abspath(__file__)) + return os.path.join(base_path, relative_path) \ No newline at end of file diff --git "a/\303\274bersicht.svg" "b/\303\274bersicht.svg" new file mode 100644 index 0000000..e0b6750 --- /dev/null +++ "b/\303\274bersicht.svg" @@ -0,0 +1,217 @@ + + + + + + +packages_neu + + + +Bauer + +Bauer + + + +FigurBuilder + +FigurBuilder + + + +Bauer->FigurBuilder + + + + + +Brett + +Brett + + + +Brett->Bauer + + + + + +Dame + +Dame + + + +Brett->Dame + + + + + +Dialog + +Dialog + + + +Brett->Dialog + + + + + +Feld + +Feld + + + +Brett->Feld + + + + + +Koenig + +Koenig + + + +Brett->Koenig + + + + + +Laeufer + +Laeufer + + + +Brett->Laeufer + + + + + +Springer + +Springer + + + +Brett->Springer + + + + + +Turm + +Turm + + + +Brett->Turm + + + + + +resource_path + +resource_path + + + +Brett->resource_path + + + + + +Dame->FigurBuilder + + + + + +Feld->Bauer + + + + + +Feld->Dame + + + + + +Feld->Koenig + + + + + +Feld->Laeufer + + + + + +Feld->Springer + + + + + +Feld->Turm + + + + + +FigurBuilder->resource_path + + + + + +Koenig->FigurBuilder + + + + + +Koenig->Turm + + + + + +Laeufer->FigurBuilder + + + + + +Springer->FigurBuilder + + + + + +Turm->FigurBuilder + + + + +