first commit
This commit is contained in:
2
.idea/.gitignore
generated
vendored
Normal file
2
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/workspace.xml
|
||||||
6
.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
6
.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<settings>
|
||||||
|
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||||
|
<version value="1.0" />
|
||||||
|
</settings>
|
||||||
|
</component>
|
||||||
7
.idea/misc.xml
generated
Normal file
7
.idea/misc.xml
generated
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="JavaScriptSettings">
|
||||||
|
<option name="languageLevel" value="ES6" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.6" project-jdk-type="Python SDK" />
|
||||||
|
</project>
|
||||||
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/schafkopf.iml" filepath="$PROJECT_DIR$/.idea/schafkopf.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
10
.idea/schafkopf.iml
generated
Normal file
10
.idea/schafkopf.iml
generated
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="PYTHON_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
8
.idea/untitled.iml
generated
Normal file
8
.idea/untitled.iml
generated
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="PYTHON_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$" />
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
53
src/Card.py
Normal file
53
src/Card.py
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import enum
|
||||||
|
from typing import *
|
||||||
|
from collections import namedtuple
|
||||||
|
|
||||||
|
|
||||||
|
class Card:
|
||||||
|
class Suit(enum.Enum):
|
||||||
|
Eichel = 0
|
||||||
|
Gras = 1
|
||||||
|
Herz = 2
|
||||||
|
Schellen = 3
|
||||||
|
|
||||||
|
SUITS_STR: Dict[Suit, str] = {
|
||||||
|
Suit.Eichel: "♣",
|
||||||
|
Suit.Gras: "♠",
|
||||||
|
Suit.Herz: "♥",
|
||||||
|
Suit.Schellen: "♦",
|
||||||
|
}
|
||||||
|
|
||||||
|
class Rank(enum.Enum):
|
||||||
|
Ober = 0
|
||||||
|
Unter = 1
|
||||||
|
Ass = 2
|
||||||
|
Koenig = 3
|
||||||
|
Zehn = 4
|
||||||
|
Neun = 5
|
||||||
|
Acht = 6
|
||||||
|
Sieben = 7
|
||||||
|
|
||||||
|
RANKS_STR: Dict[Rank, str] = {
|
||||||
|
Rank.Ober: "O",
|
||||||
|
Rank.Unter: "U",
|
||||||
|
Rank.Ass: "A",
|
||||||
|
Rank.Koenig: "K",
|
||||||
|
Rank.Zehn: "X",
|
||||||
|
Rank.Neun: "9",
|
||||||
|
Rank.Acht: "8",
|
||||||
|
Rank.Sieben: "7",
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, suit: Suit, rank: Rank):
|
||||||
|
self.suit: Card.Suit = suit
|
||||||
|
self.rank: Card.Rank = rank
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "\n".join(self.glyph())
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "Card: <" + self.suit.name + ", " + self.rank.name + ">"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
35
src/ConsoleRenderer.py
Normal file
35
src/ConsoleRenderer.py
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
from Renderer import Renderer
|
||||||
|
from typing import List
|
||||||
|
from Player import Player
|
||||||
|
from Card import Card
|
||||||
|
from Glyph import side_by_side_glyphs, stacked_glyphs, glyph_to_colored_string
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
class ConsoleRenderer(Renderer):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.header = ""
|
||||||
|
self.stack = ""
|
||||||
|
self.hand = ""
|
||||||
|
|
||||||
|
def render_stack(self, cards: List[Card]):
|
||||||
|
self.stack = glyph_to_colored_string(stacked_glyphs(cards))
|
||||||
|
self.rerender()
|
||||||
|
|
||||||
|
def render_hand(self, player: Player):
|
||||||
|
self.hand = player.get_name() + "'s hand:\n" + \
|
||||||
|
glyph_to_colored_string(side_by_side_glyphs(player.card_options()))
|
||||||
|
self.rerender()
|
||||||
|
|
||||||
|
def render_message(self, message: str):
|
||||||
|
self.header = message
|
||||||
|
self.rerender()
|
||||||
|
|
||||||
|
def rerender(self):
|
||||||
|
os.system("clear")
|
||||||
|
print(self.header)
|
||||||
|
print()
|
||||||
|
print("Current Stack: ")
|
||||||
|
print(self.stack)
|
||||||
|
print(self.hand)
|
||||||
11
src/Deck.py
Normal file
11
src/Deck.py
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
from Card import Card
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
|
||||||
|
class Deck(list):
|
||||||
|
def __init__(self):
|
||||||
|
deck = []
|
||||||
|
for rank in Card.Rank:
|
||||||
|
for suit in Card.Suit:
|
||||||
|
deck.append(Card(suit, rank))
|
||||||
|
super().__init__(deck)
|
||||||
12
src/Errors.py
Normal file
12
src/Errors.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
class SchafkopfError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class RoundLevelError(SchafkopfError):
|
||||||
|
def __init__(self, message):
|
||||||
|
self.message = message
|
||||||
|
|
||||||
|
|
||||||
|
class GameLevelError(SchafkopfError):
|
||||||
|
def __init__(self, message):
|
||||||
|
self.message = message
|
||||||
88
src/Game.py
Normal file
88
src/Game.py
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
from Player import Player
|
||||||
|
from typing import List
|
||||||
|
from Round import Round
|
||||||
|
from RufSpiel import RufSpiel
|
||||||
|
from Card import Card
|
||||||
|
from Deck import Deck
|
||||||
|
from Renderer import Renderer
|
||||||
|
from Errors import GameLevelError
|
||||||
|
import random as rn
|
||||||
|
from itertools import cycle
|
||||||
|
|
||||||
|
|
||||||
|
Stack = List[Card]
|
||||||
|
|
||||||
|
|
||||||
|
class Game:
|
||||||
|
def __init__(self, players: List[Player], renderer: Renderer):
|
||||||
|
if len(players) != 4:
|
||||||
|
raise GameLevelError("There must be exactly four players, but received " + str(len(players)) + "!")
|
||||||
|
self.players: List[Player] = players
|
||||||
|
self.game_over: bool = False
|
||||||
|
self.renderer = renderer
|
||||||
|
self.deck = Deck()
|
||||||
|
self.stack: List[Card] = []
|
||||||
|
self.current_round: Round = RufSpiel(self.players)
|
||||||
|
|
||||||
|
def play(self):
|
||||||
|
self.renderer.render_message("Game start!")
|
||||||
|
while not self.game_over:
|
||||||
|
self.current_round = Round(self.players)
|
||||||
|
self.play_round()
|
||||||
|
self.game_over = True
|
||||||
|
self.renderer.render_message("Game end!")
|
||||||
|
|
||||||
|
def play_round(self):
|
||||||
|
self.deal_cards()
|
||||||
|
while not self.current_round.is_over():
|
||||||
|
self.stack.clear()
|
||||||
|
self.round_turn()
|
||||||
|
self.renderer.render()
|
||||||
|
self.current_round.next_turn()
|
||||||
|
|
||||||
|
def round_turn(self):
|
||||||
|
self.renderer.render_message("Turn {} start.".format(self.current_round.turns_taken() + 1))
|
||||||
|
for i in range(len(self.players)):
|
||||||
|
self.renderer.render_hand(self.current_player())
|
||||||
|
self.make_move_for_current_player()
|
||||||
|
self.renderer.render_stack(self.stack)
|
||||||
|
if self.current_round.turn_in_progress():
|
||||||
|
self.current_round.move_turn_to_next_player()
|
||||||
|
self.renderer.render_message("Turn end.")
|
||||||
|
|
||||||
|
def deal_cards(self) -> None:
|
||||||
|
rn.shuffle(self.deck)
|
||||||
|
player_iterator = cycle(self.players)
|
||||||
|
for i in range(0, len(self.deck), 4):
|
||||||
|
dealt_cards = self.deck[i:i + 4]
|
||||||
|
next(player_iterator).deal_cards(*dealt_cards)
|
||||||
|
|
||||||
|
def current_player(self):
|
||||||
|
return self.players[self.current_round.get_current_player_index()]
|
||||||
|
|
||||||
|
def make_move_for_current_player(self) -> None:
|
||||||
|
cards_to_choose_from: List[Card] = self.current_player().card_options()
|
||||||
|
card_index_choice = None
|
||||||
|
while card_index_choice is None:
|
||||||
|
try:
|
||||||
|
attempt = int(input("Choose a card -> "))
|
||||||
|
if len(cards_to_choose_from) >= attempt > 0:
|
||||||
|
card_index_choice = attempt - 1
|
||||||
|
else:
|
||||||
|
print("Choice was outside card range.")
|
||||||
|
except ValueError:
|
||||||
|
print("Invalid choice.")
|
||||||
|
self.stack.append(self.current_player().play_card(card_index_choice))
|
||||||
|
|
||||||
|
def last_cards_played(self, num_cards: int) -> Stack:
|
||||||
|
if len(self.stack) == 0:
|
||||||
|
return []
|
||||||
|
elif len(self.stack) == 1:
|
||||||
|
return [self.stack[0]]
|
||||||
|
else:
|
||||||
|
if num_cards > len(self.stack):
|
||||||
|
num_cards = len(self.stack)
|
||||||
|
return self.stack[-num_cards:]
|
||||||
|
|
||||||
|
def get_stack(self) -> Stack:
|
||||||
|
return self.stack.copy()
|
||||||
95
src/Glyph.py
Normal file
95
src/Glyph.py
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
from typing import Dict, List
|
||||||
|
from Card import Card
|
||||||
|
from collections import namedtuple
|
||||||
|
|
||||||
|
|
||||||
|
SUIT_COLOR: Dict[Card.Suit, str] = {
|
||||||
|
Card.Suit.Eichel: "Black",
|
||||||
|
Card.Suit.Gras: "Green",
|
||||||
|
Card.Suit.Herz: "Red",
|
||||||
|
Card.Suit.Schellen: "Yellow",
|
||||||
|
}
|
||||||
|
CARD_GLYPH_CHARS: List[str] = [
|
||||||
|
"R S",
|
||||||
|
" ",
|
||||||
|
" S ",
|
||||||
|
" ",
|
||||||
|
"S R",
|
||||||
|
]
|
||||||
|
CARD_GLYPH_COLOR: List[str] = [
|
||||||
|
"QWWWWWS",
|
||||||
|
"WWWWWWW",
|
||||||
|
"WWWSWWW",
|
||||||
|
"WWWWWWW",
|
||||||
|
"SWWWWWQ",
|
||||||
|
]
|
||||||
|
C_COLOR: Dict[str, str] = {
|
||||||
|
"Green": "\033[32;107m",
|
||||||
|
"Red": "\033[31;107m",
|
||||||
|
"Yellow": "\033[33;107m",
|
||||||
|
"Black": "\033[30;107m",
|
||||||
|
"ResetAll": "\033[0m",
|
||||||
|
"TextReset": "\033[0m",
|
||||||
|
"BgReset": "\033[1;30m",
|
||||||
|
}
|
||||||
|
Glyph = namedtuple("Glyph", "chars colors")
|
||||||
|
C_COLOR_FROM_GLYPH_CHAR: Dict[str, str] = {
|
||||||
|
"Q": C_COLOR["Black"],
|
||||||
|
"R": C_COLOR["Red"],
|
||||||
|
"G": C_COLOR["Green"],
|
||||||
|
"Y": C_COLOR["Yellow"],
|
||||||
|
"D": C_COLOR["ResetAll"],
|
||||||
|
"W": C_COLOR["Black"],
|
||||||
|
}
|
||||||
|
GLYPH_CHAR: Dict[str, str] = {
|
||||||
|
"Black": "Q",
|
||||||
|
"Red": "R",
|
||||||
|
"Green": "G",
|
||||||
|
"Yellow": "Y",
|
||||||
|
"Default": "D",
|
||||||
|
"WhiteBg": "W",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def glyph_for(card: Card) -> Glyph:
|
||||||
|
glyph = Glyph(CARD_GLYPH_CHARS.copy(), CARD_GLYPH_COLOR.copy())
|
||||||
|
for i, line in enumerate(glyph.chars):
|
||||||
|
glyph.chars[i] = line.replace("S", Card.SUITS_STR[card.suit]).replace("R", Card.RANKS_STR[card.rank])
|
||||||
|
for i, line in enumerate(glyph.colors):
|
||||||
|
glyph.colors[i] = line.replace("S", GLYPH_CHAR[SUIT_COLOR[card.suit]])
|
||||||
|
return glyph
|
||||||
|
|
||||||
|
|
||||||
|
def glyph_to_colored_string(glyph):
|
||||||
|
out = ""
|
||||||
|
for chars_line, colors_line in zip(glyph.chars, glyph.colors):
|
||||||
|
for char, color_code in zip(chars_line, colors_line):
|
||||||
|
out += C_COLOR_FROM_GLYPH_CHAR[color_code] + char + C_COLOR["ResetAll"]
|
||||||
|
out += "\n"
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def side_by_side_glyphs(cards: List[Card]) -> Glyph:
|
||||||
|
glyph = Glyph([""] * len(CARD_GLYPH_CHARS), [""] * len(CARD_GLYPH_CHARS))
|
||||||
|
for card in cards:
|
||||||
|
for i, glyph_char_line in enumerate(glyph_for(card).chars):
|
||||||
|
glyph.chars[i] += glyph_char_line + " "
|
||||||
|
for i, glyph_color_line in enumerate(glyph_for(card).colors):
|
||||||
|
glyph.colors[i] += glyph_color_line + GLYPH_CHAR["Default"]
|
||||||
|
return glyph
|
||||||
|
|
||||||
|
|
||||||
|
def stacked_glyphs(cards: List[Card]):
|
||||||
|
result_width = len(CARD_GLYPH_CHARS[0]) + len(cards) - 1
|
||||||
|
result_height = len(CARD_GLYPH_CHARS) + len(cards) - 1
|
||||||
|
result = Glyph([" " * result_width] * result_height, [GLYPH_CHAR["Default"] * result_width] * result_height)
|
||||||
|
for i, card in enumerate(reversed(cards)):
|
||||||
|
origin_coord = [i, i]
|
||||||
|
for j, (chars_line, glyph_colors_line) in enumerate(zip(glyph_for(card).chars, glyph_for(card).colors)):
|
||||||
|
chars_out = result.chars[j + origin_coord[0]]
|
||||||
|
colors_out = result.colors[j + origin_coord[0]]
|
||||||
|
chars_out = chars_out[:origin_coord[1]] + chars_line
|
||||||
|
colors_out = colors_out[:origin_coord[1]] + glyph_colors_line
|
||||||
|
result.chars[j + origin_coord[0]] = chars_out
|
||||||
|
result.colors[j + origin_coord[0]] = colors_out
|
||||||
|
return result
|
||||||
52
src/Player.py
Normal file
52
src/Player.py
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
from typing import List, Tuple
|
||||||
|
from Card import Card
|
||||||
|
from copy import deepcopy
|
||||||
|
|
||||||
|
|
||||||
|
Hand = List[Card]
|
||||||
|
Trick = Tuple[Card, Card, Card, Card]
|
||||||
|
|
||||||
|
|
||||||
|
class Player:
|
||||||
|
Id = int
|
||||||
|
instances = 0
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_new_id(cls):
|
||||||
|
new_id = cls.instances
|
||||||
|
cls.instances += 1
|
||||||
|
return new_id
|
||||||
|
|
||||||
|
def __init__(self, name: str):
|
||||||
|
self.id = self.get_new_id()
|
||||||
|
self.name: str = name
|
||||||
|
self.hand: Hand = []
|
||||||
|
self.tricks: List[Trick] = []
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
def deal_cards(self, *cards: List[Card]) -> None:
|
||||||
|
self.hand += cards
|
||||||
|
|
||||||
|
def card_options(self) -> List[Card]:
|
||||||
|
return self.hand.copy()
|
||||||
|
|
||||||
|
def add_trick(self, trick: Trick) -> None:
|
||||||
|
self.tricks.append(trick)
|
||||||
|
|
||||||
|
def play_card(self, card_index) -> Card:
|
||||||
|
return self.hand.pop(card_index)
|
||||||
|
|
||||||
|
def reset(self) -> None:
|
||||||
|
self.tricks = []
|
||||||
|
self.hand = []
|
||||||
|
|
||||||
|
def tricks(self) -> List[Trick]:
|
||||||
|
return deepcopy(self.tricks)
|
||||||
|
|
||||||
|
def get_name(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
def get_id(self) -> int:
|
||||||
|
return self.id
|
||||||
20
src/Renderer.py
Normal file
20
src/Renderer.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
from Player import Player
|
||||||
|
from Card import Card
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
|
||||||
|
class Renderer:
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def render_stack(self, cards: List[Card]):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def render_hand(self, player: Player):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def render_message(self, message: str):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def render(self) -> None:
|
||||||
|
pass
|
||||||
39
src/Round.py
Normal file
39
src/Round.py
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
from Player import Player
|
||||||
|
from Errors import RoundLevelError
|
||||||
|
from typing import List
|
||||||
|
import random as rn
|
||||||
|
|
||||||
|
|
||||||
|
class Round:
|
||||||
|
def __init__(self, players: List[Player]):
|
||||||
|
self.current_player_index: int = 0
|
||||||
|
self.round_ended: bool = False
|
||||||
|
self.turn_number: int = 1
|
||||||
|
self.moves_left_in_turn: int = len(players)
|
||||||
|
self.num_players = len(players)
|
||||||
|
|
||||||
|
def gen_player_list(self, players: List[Player]):
|
||||||
|
return list(map(lambda x: x.get_id(), players))
|
||||||
|
|
||||||
|
def turns_taken(self) -> int:
|
||||||
|
return self.turn_number - 1
|
||||||
|
|
||||||
|
def turn_in_progress(self) -> bool:
|
||||||
|
return self.moves_left_in_turn > 0
|
||||||
|
|
||||||
|
def is_over(self) -> bool:
|
||||||
|
return self.round_ended or self.turn_number > 8
|
||||||
|
|
||||||
|
def next_turn(self) -> None:
|
||||||
|
self.turn_number += 1
|
||||||
|
self.current_player_index = 0
|
||||||
|
|
||||||
|
def move_turn_to_next_player(self) -> None:
|
||||||
|
if not self.turn_in_progress():
|
||||||
|
raise RoundLevelError("Cannot move to the next player if all players have already made their move!")
|
||||||
|
self.current_player_index += 1
|
||||||
|
if self.current_player_index >= self.num_players:
|
||||||
|
self.current_player_index = 0
|
||||||
|
|
||||||
|
def get_current_player_index(self) -> int:
|
||||||
|
return self.current_player_index
|
||||||
11
src/RufSpiel.py
Normal file
11
src/RufSpiel.py
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
from Card import Card
|
||||||
|
from Player import Player, Player.Id
|
||||||
|
from typing import List
|
||||||
|
from Round import Round
|
||||||
|
|
||||||
|
|
||||||
|
class RufSpiel(Round):
|
||||||
|
def __init__(self, players: List[Player], spieler_id: Player.Id, spieler):
|
||||||
|
super().__init__(players)
|
||||||
|
self.variable_trump: Card.Suit = Card.Suit.Herz
|
||||||
|
self.spieler: Player.Id =
|
||||||
0
src/__init__.py
Normal file
0
src/__init__.py
Normal file
BIN
src/__pycache__/Card.cpython-36.pyc
Normal file
BIN
src/__pycache__/Card.cpython-36.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/ConsoleRenderer.cpython-36.pyc
Normal file
BIN
src/__pycache__/ConsoleRenderer.cpython-36.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/Deck.cpython-36.pyc
Normal file
BIN
src/__pycache__/Deck.cpython-36.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/Errors.cpython-36.pyc
Normal file
BIN
src/__pycache__/Errors.cpython-36.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/Game.cpython-36.pyc
Normal file
BIN
src/__pycache__/Game.cpython-36.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/Glyph.cpython-36.pyc
Normal file
BIN
src/__pycache__/Glyph.cpython-36.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/Player.cpython-36.pyc
Normal file
BIN
src/__pycache__/Player.cpython-36.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/Renderer.cpython-36.pyc
Normal file
BIN
src/__pycache__/Renderer.cpython-36.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/Round.cpython-36.pyc
Normal file
BIN
src/__pycache__/Round.cpython-36.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/RufSpiel.cpython-36.pyc
Normal file
BIN
src/__pycache__/RufSpiel.cpython-36.pyc
Normal file
Binary file not shown.
33
src/main.py
Normal file
33
src/main.py
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
from typing import List
|
||||||
|
from Player import Player
|
||||||
|
from Game import Game
|
||||||
|
from ConsoleRenderer import ConsoleRenderer
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
players: List[Player] = get_players()
|
||||||
|
renderer = ConsoleRenderer()
|
||||||
|
game: Game = Game(players, renderer)
|
||||||
|
game.play()
|
||||||
|
|
||||||
|
|
||||||
|
def get_players():
|
||||||
|
return get_default_players()
|
||||||
|
|
||||||
|
|
||||||
|
def get_default_players() -> List[Player]:
|
||||||
|
names = ["Andy", "Ben", "Chris", "Daniel"]
|
||||||
|
return list(map(Player, names))
|
||||||
|
|
||||||
|
|
||||||
|
def get_input_players() -> List[Player]:
|
||||||
|
print("Who's playing?")
|
||||||
|
p1 = Player(input("Player 1: "))
|
||||||
|
p2 = Player(input("Player 2: "))
|
||||||
|
p3 = Player(input("Player 3: "))
|
||||||
|
p4 = Player(input("Player 4: "))
|
||||||
|
return [p1, p2, p3, p4]
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
10
src/tests.py
Normal file
10
src/tests.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import unittest
|
||||||
|
from Player import Player, PlayerLoop
|
||||||
|
|
||||||
|
|
||||||
|
class MyTestCase(unittest.TestCase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
Reference in New Issue
Block a user