updated roles, init tests, added states

This commit is contained in:
2021-03-12 00:59:38 +01:00
parent 8654e795fe
commit c6e8cc7d29
6 changed files with 193 additions and 39 deletions

View File

@@ -1,3 +1,53 @@
# PyWerwolf
Trying to rebuild [https://github.com/foin137/werwolfonline.eu](https://github.com/foin137/werwolfonline.eu) in python
## Phases of the game
```plantuml
@startuml
[*] --> WaitingForPlayers: Created
WaitingForPlayers : Show the game id/link
WaitingForPlayers : Create game in Database
WaitingForPlayers : Allow setting of rules
WaitingForPlayers --> StartGame: len(Players)>=len(special roles) && start && num_werewolfes > 1
WaitingForPlayers --> WaitingForPlayers: start && (len(Players)<len(special roles) || num_werewolfes < 1)
StartGame : Assign Player Roles
StartGame : Show Introduction
state GameHasCupin <<choice>>
state NightPhaseCupin <<fork>>
StartGame --> GameHasCupin : all ready
GameHasCupin --> NightPhaseCupin: Game has Cupin
GameHasCupin --> NightPhaseMain: no Cupin
NightPhaseMain : Werewolfes awake & select (vote) their victim
NightPhaseMain : Seer/Spy/Protector/ParanormalInvestigator awaken & access feat
NightPhaseMain : sleep & confirm
state NightPhaseCupinEnd <<join>>
NightPhaseCupin --> WaitToContinueCupin: !Cupin
NightPhaseCupin --> SelectLovedOnes: Cupin
WaitToContinueCupin --> NightPhaseCupinEnd
SelectLovedOnes --> NightPhaseCupinEnd: selected and confirmed loved ones
state NightPhaseLovedOnes <<fork>>
state NightPhaseLovedOnesEnd <<fork>>
NightPhaseCupinEnd --> NightPhaseLovedOnes
NightPhaseLovedOnes --> LovedOnesAwake: Selected Loved Ones
NightPhaseLovedOnes --> WaitForLovedOnes: other
LovedOnesAwake --> NightPhaseLovedOnesEnd: ready
WaitForLovedOnes --> NightPhaseLovedOnesEnd
NightPhaseLovedOnesEnd --> NightPhaseMain : all ready
NightPhaseMain --> NightPhaseLate : Witch/Leaderwolf && voted && actions done and all ready
NightPhaseLate: LeaderWolf selects victim to convert
NightPhaseLate: witch is allowed to select heal/murder
NightPhaseMain --> ShowDead: no Witch/Leaderwolf && voted && actions done and all ready
NightPhaseLate --> ShowDead: actions taken
@enduml
```

View File

@@ -1,3 +1,60 @@
import models
from pywerwolf import models
import typing as t
import uuid
class Game(object):
state: models.GameState
def __init__(self, game_id: t.Union[str, uuid.UUID] = None):
if game_id is None:
self.create_new_game_state()
else:
self.load_game_state(game_id)
def create_new_game_state(self):
pass
def load_game_state(self, game_id: t.Union[str, uuid.UUID]):
pass
def valid_game(self):
# check if game has been created or loaded
return True
def check_victory(self):
"""check for a winner of the current game"""
if not self.valid_game():
return None
if self.state.currentPhase == models.GamePhase.Award:
return True
if sum(1 for _ in self.werewolfes) > 0:
if sum(1 for _ in self.villagers) <= 0:
return models.RoleGroup.Werewolfs
pass
else:
return models.RoleGroup.Villagers
if sum(1 for _ in self.player_alive) == 2:
living = list(self.player_alive)
if living[0].lovedOne == living[1]:
return models.RoleGroup.LovedOnes
return None
@property
def player_alive(self):
"""Generator for players still alive"""
return filter(lambda x: x.alive, self.state.players)
@property
def werewolfes(self):
"""Generator for players that are werewolfes"""
return filter(models.Player.isWerwolf, self.player_alive)
@property
def villagers(self):
"""Generator for players that are villagers"""
return filter(not (models.Player.isWerwolf), self.player_alive)

View File

@@ -21,6 +21,13 @@ class GamePhase(enum.Enum):
PollResult = enum.auto()
Award = enum.auto()
class RoleGroup(enum.Enum):
NoGroup = enum.auto()
Villagers = enum.auto()
Werewolfs = enum.auto()
LovedOnes = enum.auto()
class Roles(enum.Enum):
NoRole = enum.auto()
Villager = enum.auto()
@@ -31,35 +38,52 @@ class Roles(enum.Enum):
Cupid = enum.auto()
Protector = enum.auto()
ParanormalInvestigator = enum.auto()
Lycantrop = enum.auto()
Lycantroph = enum.auto()
Spy = enum.auto()
Murder = enum.auto()
Pacifist = enum.auto()
OldMan = enum.auto()
Murder = enum.auto()
Leaderwolf = enum.auto()
@classmethod
def isWerwolf(cls, role: Roles):
return role in [cls.Werewolf, cls.Leaderwolf]
@classmethod
def getGroup(cls, role: Roles):
return RoleGroup.Werewolfs if role in [cls.Werewolf, cls.Leaderwolf] else RoleGroup.Villagers
class Rules(object):
showRoles: bool #`charaktereAufdecken` INT ( 2 ) DEFAULT 0,
passMajor: bool #`buergermeisterWeitergeben` INT ( 2 ) DEFAULT 0,
seerSeesIdentity: bool #`seherSiehtIdentitaet` INT ( 2 ) DEFAULT 1,
roleCount: t.Dict[Roles, int]
#`werwolfzahl` INT ( 5 ) DEFAULT 0 ,
#`hexenzahl` INT ( 5 ) DEFAULT 0 ,
#`seherzahl` INT ( 5 ) DEFAULT 0 ,
#`jaegerzahl` INT ( 5 ) DEFAULT 0 ,
#`amorzahl` INT ( 2 ) DEFAULT 0 ,
#`beschuetzerzahl` INT ( 5 ) DEFAULT 0 ,
#`parErmZahl` INT (5) DEFAULT 0 ,
#`lykantrophenzahl` INT ( 5 ) DEFAULT 0 ,
#`spionezahl` INT ( 5 ) DEFAULT 0 ,
#`idiotenzahl` INT ( 5 ) DEFAULT 0 ,
#`pazifistenzahl` INT ( 5 ) DEFAULT 0 ,
#`altenzahl` INT ( 5 ) DEFAULT 0 ,
#`urwolfzahl` INT ( 5 ) DEFAULT 0 ,
werewolfes: int
witches: int
seers: int
hunters: int
cupids: int
protectors: int
paranormals: int
lycantrophs: int
spys: int
murders: int
pacifists: int
oldmans: int
leaderwolfs: int
randomSelect: bool #`zufaelligeAuswahl` INT ( 2 ) DEFAULT 0 ,
randomBonus: int #`zufaelligeAuswahlBonus` INT ( 5 ) DEFAULT 0 ,
unanimously: bool #`werwolfeinstimmig` INT ( 2 ) DEFAULT 1 ,
timer_unanimously: int
timer_unanimously_per_wolf: int
timer_unsuccessfull: int
timer_unsuccessfull_per_wolf: int
timer_accusation: int
timer_accusation_per_player: int
timer_votation: int
timer_votation_per_player: int
timer_inactivity: int
timer_inactivity_per_player: int
@@ -74,6 +98,10 @@ class Player(object):
diedInRound: int
accusedBy: "Player"
@property
def isWerwolf(self):
return Roles.isWerwolf(self.role)
# `wahlAuf` INT ( 5 ) DEFAULT -1 ,
# `angeklagtVon` INT ( 5 ) DEFAULT -1 ,
@@ -92,29 +120,11 @@ class Player(object):
# `countdownBis` INT (10) DEFAULT 0 ,
# `countdownAb` INT (10) DEFAULT 0 ,
class Game(object):
class GameState(object):
currentPhase: GamePhase #`spielphase` INT( 5 ) DEFAULT 0,
gameRound: int
rules: Rules
log: t.List[str]
players: t.List[Player]
#`werwolfopfer` INT ( 5 ) DEFAULT -1 ,
#`werwolftimer1` INT ( 10 ) DEFAULT 60 ,
#`werwolfzusatz1` INT ( 10 ) DEFAULT 4 ,
#`werwolftimer2` INT ( 10 ) DEFAULT 50 ,
#`werwolfzusatz2` INT ( 10 ) DEFAULT 3 ,
#`dorftimer` INT ( 10 ) DEFAULT 550 ,
#`dorfzusatz` INT ( 10 ) DEFAULT 10 ,
#`dorfstichwahltimer` INT ( 10 ) DEFAULT 200 ,
#`dorfstichwahlzusatz` INT ( 10 ) DEFAULT 5 ,
#`inaktivzeit` INT ( 10 ) DEFAULT 40 ,
#`inaktivzeitzusatz` INT ( 10 ) DEFAULT 0 ,
#`tagestext` TEXT ,
#`nacht` INT ( 5 ) DEFAULT 1 ,
#`log` LONGTEXT ,
#`list_lebe` LONGTEXT,
#`list_lebe_aktualisiert` BIGINT DEFAULT 0,
#`list_tot` LONGTEXT,
#`list_tot_aktualisiert` BIGINT DEFAULT 0,
#`waiting_for_others_time` BIGINT,
#`letzterAufruf` BIGINT

View File

@@ -54,12 +54,18 @@ texts = {
models.Roles.Cupid: "Armor",
models.Roles.Protector: "Beschützer/in",
models.Roles.ParanormalInvestigator: "Paranormaler Ermittler",
models.Roles.Lycantrop: "Lykantroph/in",
models.Roles.Lycantroph: "Lykantroph/in",
models.Roles.Spy: "Spion/in",
models.Roles.Murder: "Mordlustige(r)",
models.Roles.Pacifist: "Pazifist/in",
models.Roles.OldMan: "Der/Die Alte",
models.Roles.Leaderwolf: "Urwolf",
}
},
"role_group":{
"de": {
True : "Werwölfe",
False: "Dorfbewohner"
}
},
}

23
setup.py Normal file
View File

@@ -0,0 +1,23 @@
import setuptools
with open("README.md", "r") as fh:
long_description = fh.read()
setuptools.setup(
name="pywerwolf",
version="0.0.1",
author="Matthias Bilger",
author_email="matthias@bilger.info",
description="A Python implementation of Werewolf/Mafia game",
long_description=long_description,
long_description_content_type="text/markdown",
url="https://github.com/m42e/pywerwolf",
license="GPL",
packages=setuptools.find_packages(), # Required
classifiers=[
"Programming Language :: Python :: 3",
"Operating System :: OS Independent",
'License :: Other/Proprietary License',
],
python_requires='>=3.6',
)

8
tests/test_game.py Normal file
View File

@@ -0,0 +1,8 @@
import pytest
import pywerwolf
import pywerwolf.gamelogic as gl
def test_game_init():
g = gl.Game()