Compare commits
8
Commits
a9ef19ee52
...
v0.2.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
48f8998d7c | ||
|
|
17ccd3b61a | ||
|
|
1fc55d90f3 | ||
|
|
0a83d27962 | ||
|
|
06474e7f68 | ||
|
|
d7648a196c | ||
|
|
db3f71592c | ||
|
|
69b30552cb |
No files matched your search
@@ -1,25 +1,28 @@
|
||||
# kostky
|
||||
|
||||
Textová (CLI) hra v kostky pro více hráčů – varianta klasického *Farkle*
|
||||
(„tisícovky“). Běží celá v terminálu a je napsaná v čistém Pythonu bez
|
||||
externích závislostí.
|
||||
(„tisícovky“). Běží celá v terminálu, v Pythonu, s jedinou závislostí
|
||||
(`tabulate` pro závěrečnou výsledkovou tabulku).
|
||||
|
||||
## Požadavky
|
||||
|
||||
- Python 3.7+ (hra se spoléhá na zachování pořadí klíčů ve slovníku)
|
||||
- Žádné externí balíčky – používá se jen standardní knihovna
|
||||
(`random`, `os`, `re`, `csv`, `collections`, `typing`)
|
||||
- Python 3.9+
|
||||
- Závislost `tabulate` (doinstaluje se automaticky při instalaci)
|
||||
|
||||
## Spuštění
|
||||
## Instalace a spuštění
|
||||
|
||||
```bash
|
||||
git clone https://gitea.spacilovi.eu/david/kostky.git
|
||||
cd kostky
|
||||
python main.py
|
||||
pip install .
|
||||
kostky
|
||||
```
|
||||
|
||||
> Hru spouštěj z adresáře projektu – soubor `hodnoty.csv` (bodovací tabulka)
|
||||
> se načítá relativní cestou vůči aktuálnímu adresáři.
|
||||
Případně bez instalace (s nainstalovaným `tabulate`) přes `python -m kostky`,
|
||||
nebo izolovaně jako CLI nástroj přes `pipx install .`.
|
||||
|
||||
> Pro vývoj: `pip install -e ".[dev]"` – editovatelná instalace včetně `mypy`
|
||||
> a `ruff`.
|
||||
|
||||
## Jak se hraje
|
||||
|
||||
@@ -31,42 +34,45 @@ python main.py
|
||||
|
||||
### Průběh tahu
|
||||
|
||||
Na začátku tahu uvidíš cílové skóre, kdo je na tahu (a jeho celkové skóre)
|
||||
a hod šesti kostkami s očíslovanými pozicemi:
|
||||
Na začátku tahu uvidíš, kdo je na tahu (s jeho skóre a cílem), a hod šesti
|
||||
kostkami s písmennými pozicemi:
|
||||
|
||||
```
|
||||
Vítězné skóre: 10000.
|
||||
Na tahu je Anna (0).
|
||||
Na tahu je Anna (0/10000).
|
||||
1, 5, 3, 2, 6, 4
|
||||
^ ^ ^ ^ ^ ^
|
||||
1 2 3 4 5 6
|
||||
a b c d e f
|
||||
```
|
||||
|
||||
Pak zvolíš jednu z akcí:
|
||||
|
||||
| Vstup | Akce |
|
||||
| --- | --- |
|
||||
| `pozice kostek` | Odložíš vybrané kostky k vyhodnocení (např. `1`, `34`, `123456`). Hodnoty na zvolených pozicích musí dohromady tvořit některou kombinaci z bodovací tabulky. |
|
||||
| `pozice kostek` | Odložíš vybrané kostky k vyhodnocení – písmeny (např. `a`, `cd`, `abcdef`). Hodnoty na zvolených pozicích musí dohromady tvořit některou kombinaci z bodovací tabulky. |
|
||||
| `h` | Hodíš znovu zbývajícími kostkami. Povoleno až poté, co v tomto tahu odložíš aspoň jednu bodující kombinaci. |
|
||||
| `k` | Ukončíš tah, připíšeš si nasbírané skóre a předáš tah dalšímu hráči. |
|
||||
| `exit` | Předčasně ukončíš celou hru. |
|
||||
|
||||
Odkládat můžeš i víc kombinací po sobě – po každém vyhodnocení pokračuješ se
|
||||
zbývajícími kostkami a body se v rámci tahu sčítají.
|
||||
|
||||
### Smůla, hot dice a výhra
|
||||
### Smůla, hot dice, vynulování a výhra
|
||||
|
||||
- **Smůla (bust):** když čerstvý hod neobsahuje žádnou bodující kombinaci,
|
||||
o body z tohoto tahu přijdeš a tah přechází na dalšího hráče.
|
||||
- **Hot dice:** když se ti podaří odložit všech šest kostek, dostaneš čerstvý
|
||||
hod šesti kostkami a pokračuješ ve stejném tahu.
|
||||
- **Výhra:** po dokončení každého kola se kontroluje, jestli někdo dosáhl
|
||||
cílového skóre. Vyhrává osamocený lídr nad limitem; při shodě na první
|
||||
příčce se hraje dál.
|
||||
- **Vynulování:** tři po sobě jdoucí nulové tahy vynulují tvé celkové skóre.
|
||||
Počet aktuálních nul se vedle skóre ukazuje jako `x` / `xx`.
|
||||
- **Výhra:** po dokončení každého kola vyhrává osamocený lídr nad cílovým
|
||||
skóre; při shodě na první příčce se hraje dál. Na konci se vypíše výsledková
|
||||
tabulka s pořadím všech hráčů.
|
||||
|
||||
## Bodování
|
||||
|
||||
Kompletní tabulka je v souboru [`hodnoty.csv`](hodnoty.csv). Kombinace se
|
||||
vyhodnocuje podle hodnot odložených kostek – na jejich pořadí nezáleží.
|
||||
Kompletní tabulka je v souboru [`kostky/hodnoty.csv`](kostky/hodnoty.csv).
|
||||
Kombinace se vyhodnocuje podle hodnot odložených kostek – na jejich pořadí
|
||||
nezáleží.
|
||||
|
||||
### Stejné kostky
|
||||
|
||||
|
||||
+42
-28
@@ -1,10 +1,11 @@
|
||||
from typing import Any
|
||||
from random import randint
|
||||
from os import system, name
|
||||
import re
|
||||
from importlib.resources import files
|
||||
import csv
|
||||
import re
|
||||
from collections import Counter
|
||||
from importlib.resources import files
|
||||
from os import name, system
|
||||
from random import randint
|
||||
from typing import Any
|
||||
|
||||
from tabulate import tabulate
|
||||
|
||||
score: int = 0
|
||||
@@ -16,11 +17,10 @@ h_bool: bool = True
|
||||
aggr: dict[str, int] = {}
|
||||
final_score: int = 10000
|
||||
|
||||
with open("hodnoty.csv", "r") as csv_file:
|
||||
csv_text = files(__package__).joinpath("hodnoty.csv").read_text(encoding="utf-8")
|
||||
csv_reader = csv.reader(csv_text.splitlines())
|
||||
csv_text = files(__package__).joinpath("hodnoty.csv").read_text(encoding="utf-8")
|
||||
csv_reader = csv.reader(csv_text.splitlines())
|
||||
|
||||
for row in csv_reader:
|
||||
for row in csv_reader:
|
||||
key = str(row[0])
|
||||
value = int(row[1])
|
||||
|
||||
@@ -29,7 +29,7 @@ with open("hodnoty.csv", "r") as csv_file:
|
||||
def throw(count: int) -> str:
|
||||
count = int(count)
|
||||
new_throw: list[str] = []
|
||||
for dice in range(count):
|
||||
for _dice in range(count):
|
||||
new_throw.append(str(randint(1, 6)))
|
||||
new_throw_str: str = "".join(new_throw)
|
||||
return new_throw_str
|
||||
@@ -41,18 +41,15 @@ def show_throw(throw: str) -> str:
|
||||
|
||||
pretty_list: str = ", ".join(throw_temp)
|
||||
pretty_list += "\n"
|
||||
for i in range(1, len(throw_temp) + 1):
|
||||
for _i in range(1, len(throw_temp) + 1):
|
||||
pretty_list += "^ "
|
||||
pretty_list += "\n"
|
||||
for i in range(1, len(throw_temp) + 1):
|
||||
pretty_list += f"{i} "
|
||||
for i in range(len(throw_temp)):
|
||||
pretty_list += f"{chr(97+i)} "
|
||||
return pretty_list
|
||||
|
||||
def clear() -> None:
|
||||
if name == 'nt':
|
||||
_ = system('cls')
|
||||
else:
|
||||
_ = system('clear')
|
||||
_ = system('cls') if name == 'nt' else system('clear')
|
||||
|
||||
def evaluate(inp: Any, count: int, throw: str) -> tuple[Any, ...]:
|
||||
|
||||
@@ -78,19 +75,34 @@ def evaluate(inp: Any, count: int, throw: str) -> tuple[Any, ...]:
|
||||
pointer = nxt_key
|
||||
|
||||
inp = str(inp)
|
||||
if re.search(r"^\d+$", inp):
|
||||
inp_temp: str = ""
|
||||
|
||||
if re.search(r"^[a-f]+$", inp):
|
||||
if len(inp) > count:
|
||||
data: tuple[Any, ...] = ("msg", "ER01", "Tolika kostkami nemůžete hodit. Zkuste to znovu: ", count, throw)
|
||||
data: tuple[Any, ...] = (
|
||||
"msg",
|
||||
"ER01",
|
||||
"Tolika kostkami nemůžete hodit. Zkuste to znovu: ",
|
||||
count,
|
||||
throw
|
||||
)
|
||||
else:
|
||||
for x in inp:
|
||||
x = int(x)
|
||||
x = ord(x)-96
|
||||
if x > count:
|
||||
if count == 1:
|
||||
ran = "1"
|
||||
else:
|
||||
ran = f"1–{count}"
|
||||
data = ("msg", "ER02", f"Zvolte prosím kostky v platném rozsahu ({ran}): ", count, throw)
|
||||
ran = "1" if count == 1 else f"1–{count}"
|
||||
data = (
|
||||
"msg",
|
||||
"ER02",
|
||||
f"Zvolte prosím kostky v platném rozsahu ({ran}): ",
|
||||
count,
|
||||
throw
|
||||
)
|
||||
return data
|
||||
else:
|
||||
inp_temp += str(x)
|
||||
inp = inp_temp
|
||||
|
||||
old_throw: list[str] = []
|
||||
pick: list[str] = []
|
||||
for y in range(count):
|
||||
@@ -205,8 +217,9 @@ def add_players() -> None:
|
||||
else:
|
||||
break
|
||||
|
||||
def to_sorted_tuple(d: dict[str, int], s: bool = True) -> tuple[list[tuple[int, str, int]], dict[str, int]]:
|
||||
L: list[tuple[str, int]] = []
|
||||
def to_sorted_tuple(d: dict[str, int], s: bool = True) -> tuple[list[tuple[int, str, int]],
|
||||
dict[str, int]]:
|
||||
L: list[tuple[int, str, int]] = []
|
||||
|
||||
if s:
|
||||
d = dict(sorted(d.items(), key=lambda x: x[1], reverse=True))
|
||||
@@ -278,7 +291,8 @@ def game(data: tuple) -> None:
|
||||
if count == 0:
|
||||
count = 6
|
||||
msg: str = ("Jakou akci chcete provést?\n"
|
||||
" - Zadejte kombinaci kostek k ponechání (dojde k jejich vyhodnocení): [pozice kostek] (např. 1 nebo 34 nebo 123456).\n"
|
||||
" - Zadejte kombinaci kostek k ponechání (dojde k jejich vyhodnocení): "
|
||||
"[pozice kostek] (např. a nebo cd nebo abcdef).\n"
|
||||
" - Hodit znovu: [h].\n"
|
||||
f" - Ukončit hod a ponechat si skóre z tohoto hodu ({score}): [k].\n"
|
||||
" - Ukončit hru: [exit].\n"
|
||||
|
||||
Reference in new issue
Block a user