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 @@
+
+
+
+
+
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 @@
+
+
+
+
+