<<

Univerzita Karlova v Praze Matematicko-fyzikální fakulta BAKALÁŘSKÁ PRÁCE

Petr Sobotka Sobo Mariáš

Katedra softwarového inženýrství

Vedoucí bakalářské práce: RNDr. Jan Kofroň, Ph.D. Studijní program: informatika, programování

2009 2 Tímto bych rád poděkoval vedoucímu této práce RNDr. Janu Kofroňovi, Ph.D. a zástupci v jeho nepřítomnosti RNDr. Ondřeji Šerému za vedení práce a mnoho trpělivosti nejen ve zodpovídání dotazů, ale i pokládání kon- struktivních připomínek v průběhu tvorby.

Prohlašuji, že jsem svou bakalářskou práci napsal samostatně a výhradně s použitím citovaných pramenů. Souhlasím se zapůjčováním práce a jejím zveřejňováním.

V Praze dne 3.8.2009 Petr Sobotka

3 4 Obsah

1 Úvod 10

2 Analýza 12 2.1 Základní úvahy ...... 12 2.2 Existující implementace ...... 13 2.2.1 Re! ...... 13 2.2.2 Renonc ...... 14 2.2.3 Becherovka mariáš ...... 14 2.3 Požadavky ...... 15 2.4 Výběr technologií a jazyka ...... 17 2.5 Výběr nástrojů ...... 17

3 Návrh 18 3.1 Synchronizace ...... 19 3.2 Inteligence ...... 22 3.2.1 Odhad výsledku hry ...... 22 3.2.2 Výběr hry ...... 23 3.2.3 Flekování ...... 24 3.2.4 Licitace ...... 24 3.2.5 Odvozování karet ostatních ...... 25 3.2.6 Co nést ...... 25 3.3 Síť ...... 27 3.4 Struktura ...... 28 3.4.1 GUI ...... 28 3.4.2 Hra ...... 29 3.4.3 Hráči ...... 29 3.4.4 Inteligence ...... 30 3.4.5 Jádro ...... 31

5 3.4.6 Síť ...... 31 3.4.7 Sync ...... 31

4 SDL 32 4.1 Základní použití ...... 32 4.2 Grafika ...... 33 4.3 Text ...... 33 4.4 Síť ...... 34 4.5 Umístění ...... 35

5 Uživatelská dokumentace 36 5.1 Nároky ...... 36 5.2 Pravidla ...... 36 5.3 Ohodnocení ...... 39 5.4 Ovládání ...... 40

6 Programátorská dokumentace 44 6.1 Init ...... 44 6.2 GUI ...... 45 6.2.1 Ceske hlasky ...... 45 6.2.2 Gui ...... 45 6.3 Hra ...... 48 6.3.1 Cenik ...... 48 6.3.2 Karta ...... 49 6.3.3 Marias ...... 49 6.3.4 Stych ...... 50 6.4 Hráči ...... 50 6.4.1 Hrac ...... 50 6.5 Inteligence ...... 52 6.5.1 Co hrat ...... 52 6.5.2 Fleky ...... 53 6.5.3 Jak nest ...... 53 6.5.4 Jiny hrac ...... 56 6.5.5 Licitator ...... 57 6.5.6 Odhad vysledku ...... 58 6.6 Jádro ...... 59 6.6.1 Jadro ...... 59 6.7 Síť ...... 60 6.7.1 TCPIP spojeni ...... 60

6 6.8 Sync ...... 61 6.8.1 Sync ...... 61

7 Závěr 63

Literatura 65

A Obsah přiloženého CD-ROM 66

7 8 Název práce: Sobo Mariáš Autor: Petr Sobotka Katedra (ústav): Katedra softwarového inženýrství Vedoucí bakalářské práce: RNDr. Jan Kofroň, Ph.D. e-mail vedoucího: [email protected]ff.cuni.cz

Abstrakt: Cílem práce je softwarový projekt licitovaného mariáše. Jedná se o počítačovou hru pro jednoho uživatele se dvěma hráči, které ovládá počítač za použití algoritmů simulujících chování lidského hráče, nebo pro tři uži- vatele po síti pomocí TCP socketů. V písemné části práce je popsán vývoj aplikace od analýzy, výběru vhodných technologií, návrhu až po podrobné zdokumentování projektu z uživatelského i programátorského hlediska. Sou- částí je i souhrn pravidel licitovaného mariáše, které jsou v této hře apliko- vány. Program je napsán v C++ za použití knihovny SDL. Klíčová slova: karetní hra, mariáš, SDL

Title: Sobo Author: Petr Sobotka Department: Department of Software Engineering Supervisor: RNDr. Jan Kofroň, Ph.D. Supervisor’s e-mail address: [email protected]ff.cuni.cz

Abstract: The aim of this work is a software project of Whist. It is a com- puter game for one user against two players, which are managed by the computer using algorithms simulating the behaviour of a human player, or for three users playing over network with the help of TCP sockets. In the written part of work there is described the evolution of application from the analysis, used technologies, design to the detailed documentation from both the user’s and programmer’s point of view. Also included is the overview of the rules of Whist which are used in this game. The program is written in C++ using the library SDL.

Keywords: , Whist, SDL

9 Kapitola 1

Úvod

Licitovaný mariáš je známá česká karetní hra, která se těší velké oblibě nejen v hospodském prostředí. Cílem této práce je vytvořit počítačovou hru lici- tovaného mariáše. Konkrétně se jedná o hru pro jednoho hráče proti dvojici počítačem ovládaných hráčů nebo pro tři lidské hráče po síti. Jelikož je ma- riáš rozšířen spíše jen v České republice, neexistuje mnoho aplikací, které ji implementují (narozdíl od jiných více světově rozšířených her). To a také předchozí zkušenosti s touto hrou byly patrně nejdůležitějšími důvody pro zvolení tématu. Proč právě mariáš licitovaný? Asi jakýkoliv hráč mariáše zná mariáš volený. A také se již určitě někdy dostal do situace, kdy měl v ruce prakticky loženou drahou hru, ale jediné, co mohl, bylo nahlásit špatnou barvu a hrát betla nebo durcha. Pro nemálo hráčů bylo toto velmi frustrující, a tak se na scénu dostal mariáš licitovaný, kde, když přijdou karty, lze o dražší hry licitovat a pak je i hrát, namísto jen smutného naříkání, co by bylo, kdyby byla volba zrovna na onom hráči. Na druhou stranu je licitovaný mariáš o dost složitější a ocení ho spíše až pokročilejší hráči. S o to větším nadšením ho však prosazují! Je tedy škoda, jak málo počítačových provedení licitovaného mariáše existuje. Jedním z cílů této práce je pokusit se to napravit. Text práce se zabývá analýzou problému, použitými technologiemi, ná- vrhem projektu, návodem k použití programu a popisem implementace. V analýze se zkoumají důvody pro výběr tématu k implementaci právě lici- tovaného mariáše, popisují se již existující aplikace a nakonec se stanovují požadavky programu, který se má vytvořit. Z hlediska technologií se odů- vodňuje výběr jazyka, knihoven a nástrojů a popisují se principy jejich fun- gování spolu se způsobem použití. Návrh pak nastiňuje strukturu budou-

10 cího programu, principy, jak řešit základní problémy, a způsob komunikace jednotlivých částí během chodu programu. Uživatelská dokumentace pak poskytuje návod k používání aplikace, a to včetně úplných pravidel licitova- ného mariáše. V programátorské dokumentaci je pak popsána implementace předchozího návrhu.

11 Kapitola 2

Analýza

Tato kapitola analyzuje základní problémy implementace počítačové hry li- citovaného mariáše, hodnotí, jak dobře jsou řešeny v již existujících im- plementacích a na jejich základě stanovuje požadavky pro zde vytvářenou aplikaci. Dle těchto požadavků se pak vybírá nejvhodnější technologie, jazyk a nástroje pro jejich implementaci.

2.1 Základní úvahy

U této počítačové hry, ostatně jako asi u mnoha jiných her s umělou inteli- gencí, velmi záleží na využitém výpočetním výkonu. Přestože je snahou mít pro aplikaci co nejnižší hardwarové nároky (aby byla dostupná více uživate- lům), použití složitějších výpočtů se někdy lze jen obtížně vyhnout. Napří- klad při výběru hry zkušený hráč jen pouhým nahlédnutím do karet ihned ví, co může hrát, aniž by cokoliv počítal, avšak umělá inteligence se může k tomuto jen blížit. Zajímavou alternativou by bylo využití neuronových sítí, ty ale v tomto ani jiných zkoumaných projektech užity nejsou. Existují ale i rozhodnutí, kdy výpočtem lze dosáhnout lepších výsledků než může člověk. Například lze pozorováním minulé hry odvodit pořadí karet při složení balíku, který se pak nemíchá, ale jen jednou snímne, a tak je pak možno z obdržených karet přesně dopočíst rozložení karet ve hře (neznámou je pak jen odhozený talon pro protihráče). To téměř žádný člověk nezvládne. Stejně tak přílišné použití výpočetní síly, když už by v průběhu hry bylo jasnější, co kdo má za karty (odvozením z již vynesených karet), k vyzkoušení všech možností, jak hru dohrát, je od standardních lidských schopností až příliš vzdálené. Tedy program může buď použít maximum svých možností,

12 ale tím vytvořit téměř neomylného hráče, který by prohrával jen s opravdu špatnými kartami, a začalo by více než na schopnostech uživatele záležet na rozložení karet (náhodě), a nebo v takovýchto případech mírně snížit svou inteligenci, aby byla hra hratelnější pro širší spektrum hráčů. Smyslem hry ovšem je, aby bavila, ne aby byla téměř neporazitelná, a tedy je asi nejlepším řešením založit co nejvíce použitých algoritmů pro rozhodování na lidských možnostech, nebo dokonce (kde to jde), aby přesně kopírovaly lidské uvažování a jen ve zbytku případů se využilo hrubé výpočetní síly. V ideálním případě pak umělá inteligence hraje co nejlépe, ale rozhoduje se jen s použitím takových prostředků, které zhruba odpovídají schopnostem dobrého lidského hráče. Dále se musí brát ohled na intuitivnost (a s tím spojenou jednoduchost) ovládání hry, aby mohla mít u uživatelů úspěch. Už z toho vyplývá nutnost použít grafické prostředí, neboť karetní hra jen v textovém režimu by asi příliš hratelná nebyla. Ne každý je zvyklý na použití myši, a tak je nejlepší umožnit ovládat hru i klávesnicí. Obtížná instalace je také schopna odra- dit od výběru právě této aplikace. A přestože se výskytu chyb v programu samozřejmě téměř vyhnout nedá, lze si dát pozor na ty, co nejvíce snižují hratelnost, či na špatná rozhodnutí hráčů, která jsou nejdražší (ostatně i člověk hraje při drahé hře pozorněji).

2.2 Existující implementace

Existujících implementací skutečného licitovaného mariáše je jen velmi málo. Následující sekce zkoumá, jak se jednotlivé aplikace vypořádaly se všemi problémy a jaké mají klady či zápory.

2.2.1 Re! Asi nejznámějším licitovaným mariášem je program Re! [8] (od Jaroslava Pi- voňky). Ten je ale určen ještě pro MSDOS, a tedy se s jeho zprovozněním na novějších platformách vyskytuje řada problémů. Jednoduchá grafika s velmi intuitivním ovládáním dodávají této hře kouzlo dosud nepřekonané. Nepo- třebuje ovšem žádnou složitou instalaci a nároky jsou minimální. Inteligence počítačem ovládaných hráčů je vskutku obdivuhodná, obzvláště uváží-li se, že si program musel vystačit s tak málo prostředky, jakými měl kdysi k dis- pozici, a tedy nemohl tak snadno procházet více variant rozhodnutí a vybrat nejlepší (aniž by přitom nedošlo k výraznému zpomalení hry). Na druhou

13 stranu se ale i objevuji spekulace, že program občas má až přílišné štěstí v situacích, kdy nemohl rozložení karet tušit, a tedy že občas nahlíží do všech karet (přestože pravděpodobnost tomu napovídá, nelze to ovšem bez nahlédnutí do zdrojových kódů dokázat). V programu se objevilo i několik menších chyb, z nichž asi nejznámější byla, že při ložené hře ve stu a dvou sedmách uznal hráče vítězem, i když neměl v ruce ony sedmy. Toho šlo na- příklad využít tak, že kdykoliv měl hráč v ruce skoro ložených 150 (či více), zahlásil sto a dvě sedmy s pomocnou barvou, od kterých nic neměl, což mu samozřejmě počítač naflekoval několikrát včetně kila, a hráč byl hned po hře o několik tisíc korun bohatší. Nicméně i přes drobné nedostatky je to hra, která dokázala na dlouhé hodiny zabavit asi každého příznivce licitovaného mariáše a ještě i dnes má mnoho příznivců.

2.2.2 Renonc V minulém roce se ještě objevila jedna implementace s názvem Renonc od Václava Kozmíka [4]. Jedná se o licitovaný mariáš napsaný v C# a využí- vající XAML pro vytvoření grafického prostředí. Vektorová grafika spolu s poměrně intuitivním ovládáním myší jsou velkým plus. Trochu nevýhodou se zdají být karty s nestandardními obrázky, které, byť jsou velmi originální, mohou hráče zvyklého na normální karty velmi zmást. Zajímavostí je i řada nastavení, které hra poskytuje. Většina hráčů je ale asi bude ignorovat, ob- zvláště uváží-li se, kolik jich je a jak složitá jsou. Nicméně se určitě najdou i uživatelé, kteří je ocení. Inteligence se zdá být velmi dobrá, nicméně využití minimaxu pro druhou polovinu hry už je možná až příliš velkou zbraní v rukou počítačem řízených hráčů. Nevýhodou je také složitější instalace na systémech, které nativně neobsahují .NET Framework 3.0, jež hra vyžaduje. Za lepší grafiku (a možná i použití hrubé síly v umělé inteligenci) se také platí zvýšením zatížení hardware a nárokům hry. Tyto problémy ovšem ne- musí každému vadit, obzvláště má-li daný uživatel výkonný stroj s Windows Vista (nebo novějšími). Hra je velmi povedená a určitě ji lze fanouškům ma- riáše doporučit.

2.2.3 Becherovka mariáš Vzhledem k nízkému počtu dobrých příkladů, je v této analýze přidán i Be- cherovka mariáš [3], který je mariášem voleným. Hra má poměrně jasné ovlá- dání myší. Nicméně grafické prostředí je velmi zvláštní tím, že jsou všechny (i

14 nepotřebné) informace a nastavení neustále zobrazovány v pravé části okna, zatímco jednotliví hráči pak jsou nahoře, vlevo a dole. Nejen, že to mate, ale i ruší od uživatele od hry. Inteligence ve srovnání s předchozími není příliš vyvinutá a dělá někdy velmi zvláštní (až hloupá) rozhodnutí. Nároky na hardware jsou ovšem minimální a instalace snadná. Celkově však, přestože je hra hratelná, jak Renonc, tak Re! se zdají být lepšími alternativami.

2.3 Požadavky

Nejprve by bylo vhodné si uvědomit, pro jaké typy uživatelů bude hra vy- tvářena, a tedy tomu i přizpůsobit požadavky, které na ni budou kladeny. Skutečných expertů má licitovaný mariáš jen velmi málo. Proto bude lépe, když se hra zaměří spíše na běžné hráče. Tedy ty, kteří znají pravidla a při hře přemýšlí, ale zase ne příliš. Takže nebudou například (ať už kvůli svým schopnostem nebo míře jejich aplikace) propočítávat možné výnosy s ohle- dem na dopad na několik tahů dopředu nebo si pamatovat možné rozmístění více než těch nejdůležitějších karet ve hře. Ne každý potenciální uživatel má k dispozici herní počítač s vysokým výkonem, a proto bude nejlépe mít ná- roky hry co nejnižší. Na druhou stranu jsou ale dnešní hráči počítačových her zvyklí na lepší grafickou úroveň aplikací. Je-li ovládání hry příliš obtížné či nepřehledné, uživatel často raději zvolí hru jinou než, aby investoval svůj čas na jeho pochopení. Zatímco někteří hráči používají k ovládání her jen myš, najdou se i tací, kdo preferují klávesnici. Uživatelé také ocení, když si hru budou moci jen stáhnout a rovnou začít hrát bez potřeby instalace. Pakliže bude třeba použít nějakých knihoven, bude asi lepší, aby byly slinkovány s programem dynamicky, neboť nemálo hráčů, kteří obdobné hry hrají, je již velmi pravděpodobně budou ve svém počítači mít. Co se týče jazyka, bu- dou prakticky všichni potenciální hráči umět česky, neboť je mariáš nejvíce rozšířený právě v České (respektive Slovenské) republice. Ze všech zkoumaných aplikací z kap. 2.2 má patrně nejlepší GUI Re! [8], které je velmi jednoduché, s malými nároky na hardware a používá všem hráčům známé obrázky karet. To vyhovuje výše zmíněným nárokům, které by mohl potenciální uživatel mít, a tak je toto GUI dobrým vzorem, ze kterého se dá při tvorbě tohoto projektu vycházet. Co se týče ovládání, žádná z hodnocených aplikací neměla možnost ovládat hru myší i kláves- nicí zároveň, což by se mohlo mnohým uživatelům, jak již je výše popsáno, zamlouvat. Cena obojetnosti ovládání (vzhledem k nárokům hardwaru i k náročnosti implementace) přitom nemusí být vysoká, a tedy by bylo škoda

15 tuto možnost do programu nepřidat. Inteligence by měla být co nejvíce po- dobná lidské (a kde to nejde, tak aspoň rozumě omezená na tuto úroveň), čímž by se hra stala více hratelnou pro běžné hráče. Díky jednoduché gra- fice a mírně tlumené inteligenci by pak mimo jiné bylo možné dosáhnout nízké doby odezvy na akce uživatele, a to i při nízkém zatížení procesoru a malé hardwarové náročnosti. Aby se nemuselo nic instalovat, bylo by lepší mít hru jen jako jediný soubor, který používá jen několik málo knihoven. Jak již bylo řečeno, budou se knihovny s programem linkovat dynamicky. Menší počet takovýchto knihoven také zvýší šanci, že je hráči již mít na počítači budou. Nevýhodou statického linkování knihoven s programem je, že by zbytečně navýšilo velikost hry na disku a při spuštění více než jednoho programu by se v paměti opakoval použitý kód knihoven (zatímco u dyna- mického slinkování je takováto knihovna natažena do paměti jen jednou). Dynamické linkování pak také umožňuje, aby uživatel použil novější verzi knihoven (například kvůli zvýšení efektivity chodu knihovny v této verzi) aniž by musel sám autor programu vše znovu přeložit a distribuovat. Pro případ, že je někdo mít na počítači nebude, by je bylo vhodné přiložit přímo k aplikaci. Vzhledem k téměř jisté znalosti češtiny všech potenciálních hráčů, nemá v aplikaci smysl používat jiný jazyk než češtinu (a tedy ani nemá v tomto případě význam využívat prostředků lokalizace). Cílovou platformou budou Microsoft Windows (XP a novější), nicméně by rozhodně nebylo na škodu počítat i s budoucím rozšířením na více platforem. Souhrn požadavků: • Jednoduché a přehledné grafické prostředí • Intuitivní ovládání myší i klávesnicí • Lidsky se chovající umělá inteligence • Nízké vytížení procesoru a paměti • Svižná reakce na akce uživatele • Nízké nároky na HW • Bez instalace • Knihoven málo a jsou s programem linkovány dynamicky • Čeština (včetně diakritiky) • Možnost pozdějšího rozšíření na více platforem

16 2.4 Výběr technologií a jazyka

Použit by měl být jazyk, který je jednoduchý, platformově nezávislý a přitom nabízí objekty, dědičnost a kontejnery. Objekty spolu s dědičností (mimo jiné) zaručí lepší strukturovanost a přehlednost kódu. Kontejnery jsou pak obzvláště třeba pro práci s kartami, které bude u karetní hry velmi hodně. Takovými jazyky jsou například C++ a Java. Díky projektu Mono lze mezi ně přidat i C#. Vybrán byl, hlavně kvůli znalostem autora, C++. Pokud se ovšem chce v C++ nezávisle na platformě používat i vlákna, grafiku a práci s událostmi (například kvůli myši a klávesnici), lze to vyřešit řadou jednotlivých knihoven, které to umožňují. Ovšem pro jednoduchost práce (i následnou snadnou udržovatelnost kódu) by nebylo dobré použí- vat více různorodých knihoven, navíc by tím potenciálně narostla náročnost spuštění hry, neboť by uživatel musel všechny tyto knihovny na počítači mít. Proto je daleko lepší užití jediné knihovny, která poskytuje tuto funkcionalitu vrámci jednotného API. Takovou knihovnou je například SDL (podrobněji viz kap. 4). Nejenže je často používaná, a tedy už i prověřená řadou uživa- telů, ale také existuje řada návodů k jejímu použití, což značně ulehčí práci při programování i pozdějším udržování a rozšiřování kódu.

2.5 Výběr nástrojů

Pro práci v C++ je asi nejlepším vývojovým prostředím Visual Studio (kon- krétně je použito Visual Studio 2005). Dalším problémem je, jak všechny obrázky a fonty snadno vložit do jednoho společného binárního souboru s celou aplikací. Resources ve Visual Studio to sice řešit umí, ale ne pro více platforem. Existuje i řada knihoven, které tuto funkcionalitu poskytují i pro více platforem, ale jelikož SDL mezi nimi není, znamenalo by to při- dat použití další knihovny. Nakonec se tedy rozhodlo použít nástroj Bin2C, který je velmi jednoduchý na použití a, protože vyrobí z binárního souboru zdroje hlavičkový soubor v C, naprosto nepřekáží provozu na více platfor- mách (práce ze zdroji je pak podrobněji popsána v kap. 6.2.2). Tento text byl vytvořen za pomoci sázecího systému TeX, konkrétně balíku maker LaTeX. K tvorbě UML diagramů pak bylo použito prostředí Enterprise Architect.

17 Kapitola 3

Návrh

Hra licitovaného mariáše se skládá z několika fází popsaných v tabulce 3.1. Průběh hry je pak znázorněn ve stavovém diagramu na obrázku 3.1. Tento průběh zajistí třída Marias. Zatímco míchání, snímání, rozdání, ocenění hry, finance a přechody mezi jednotlivými fázemi jsou pevně dané, ve fázích li- citace, výběru hry, flekování a samotné hry musí rozhodovat hráči. Hráči pak jsou potomci abstraktní třídy Hrac (viz kap. 3.4.3), přičemž počítačem ovládaní hráči musí pro tato rozhodnutí používat umělé inteligence, což je blíže rozebráno v kap. 3.2.

Fáze hry Popis Míchání Zamíchání karet balíku, ale jen jednou za celou sérii her Snímání Přemístění náhodného množství karet z vrchu balíku do- spod, karty se jinak nemíchají Rozdání Rozdání karet hráčům a do talonu Licitace Rozhodnutí, kdo bude hrát (a jaký typ hry minimálně) Výběr hry Výběr hry, odhození talonu vítězem licitace Flekování Navýšení ceny hry dle toho, jak moc si hráč, respektive protihráči, věří Samotná hra Odehrají hry Ocenění hry Zjištění, kdo vyhrál a spočtení kolik Finance Finanční vyrovnání

Tabulka 3.1: Stručný popis fází průběhu hry

18 Obrázek 3.1: Diagram průběhu hry

Po spuštění aplikace se vytvoří instance její základní třídy Jadro. Ja- dro pak vše inicializuje a po celý běh programu spravuje základní vlákno programu (vlákno jádra). Aby mohla aplikace na požadavky uživatele re- agovat ihned, je třeba starat se o grafické prostředí v jiném vlákně než je jádro. Správu grafického prostředí v jejím zvláštním vlákně má na starost třída Gui (viz kap. 6.2.2). Je to právě Jadro, které spustí vlákno grafického prostředí. Role obou vláken a jejich vzájemná komunikace je pak blíže po- psána v kap. 3.1. Pro každou sérii her si pak také Jadro vytvoří instance pro všechny hráče a Marias pro řízení chodu těchto her. Jeho činnost naznačuje UML diagram na obr. 3.2. Podrobněji je Jadro popsáno v kap. 3.4.5. Kapitola 3.3 pak navrhuje způsob implementace síťové hry a konečně celková struktura projektu spolu s úlohami jednotlivých částí je popsána v kap. 3.4.

3.1 Synchronizace

Aplikace se bude skládat ze dvou uživatelských vláken. Prvním, běžícím již od začátku, bude vlákno spravující Jadro (dále vlákno jádra), druhým bude vlákno grafického prostředí. Vlákno jádra má na starost řízení chodu hry a žijí v něm i instance tříd reprezentujících hráče. Vlákno grafického prostředí

19 Obrázek 3.2: Asociace jednotlivých objektů při hře spravuje GUI, a tedy musí zpracovávat přišlé zprávy z fronty událostí (mimo jiné, aby dokázalo komunikovat s uživatelem, obzvláště obsluhovat klávesnici a myš). Na posílání dat mezi sebou mají tato vlákna řadu globálních proměnných oddělených dle funkce. Vlákno jádra vždy naplní potřebnými daty patřičné globální proměnné a poté o tom pošle zprávu (událost, ve které je i informace o tom, co se stalo, a tak i, ve kterých proměnných jsou posílaná data) a uspí se. K uspávání jádra se nejdříve používá aktivního čekání na signál (v cyklu se při tom na moment uspí a tedy pustí ostatní vlákna ke slovu) a poté, co signál obdrží, pokusí se vstoupit do semaforu (a tam se zablokuje, dokud nebude mít vlákno GUI požadavek splněný). Po probuzení tedy může s případnými daty reakce na požadavek pro GUI již volně nakládat. Vlákno grafického prostředí neustále zpracovává nové zprávy (například reakce na myš a klávesnici), a proto obdrží i případnou zprávu od jádra a provede podle ní, co je třeba (například zobrazí otázku uživateli včetně odpovědí, na které může kliknout). Při přijetí takovéto zprávy také vlákno GUI vstoupí do semaforu a nastaví signál, na který vlákno jádra aktivně

20 čeká. Po té, co je příkaz vyřízen a případná data jako reakce připravena (tedy například až uživatel vybral odpověď na položenou otázku a její index se zapsal do příslušné globální proměnné) teprve vlákno grafického prostředí vzbudí uspané vlákno jádra tak, že opustí semafor. Aktivním čekáním se urychlí komunikace obzvláště u požadavků nevyža- dujících zpětnou vazbu (přestože bere čas procesoru, bude jen velmi krátké a reakce pasivního čekání je o mnoho delší). Naopak při čekání na reakci uživatele, případně při čekání než si něco uživatel přečte, se čeká až pří- liš dlouho, a proto je zde lepší pasivní čekání. Dosáhne se tak maximální efektivnosti za nízkého zatížení procesoru. V případě ukončení uživatelem se informace o tom zapíše do příslušné globální proměnné a vlákno jádra se (pokud třeba) odblokuje. Jádro totiž ihned po každém odblokování kontroluje, zda se nemá právě hraná série her nebo celá aplikace ukončit a vše již zařídí. Tím je zajištěno, že se ukončení projeví ihned a ne až po provedení již rozdělaného úkolu (například výnosu karty). Zajímavou alternativou k použitému semaforu by byla condition variable, kterou knihovna SDL také poskytuje. Výhodou by byla větší jednoduchost z programátorského hlediska, neboť by se nemuselo používat zvlášť programo- vaného aktivního čekání a mísit to s tím. Na druhou stranu ovšem condition variable využívá i zámků, takže by se muselo zacházet i s nimi, zatímco se- mafor stačí sám o sobě. Condition variable je také méně intuitivní, neboť ne každý je na ni zvyklý a kód se tak pro řadu lidí může stát více nepřehledným. Pomyslnou výhodou navrženého postupu se semaforem může být i fakt, že při něm vlákno grafického prostředí nemůže být zablokováno. Ovšem u con- dition variable by to nastalo jen kdyby scheduler systému přepnul na cizí vlákno v momentě, kdy by vlákno jádra odeslalo zprávu GUI (a tedy ještě nestihlo uvolnit zámek), a trvalo by to nanejvýš do doby než se vlákno jádra opět dostalo ke slovu, takže vyjma velmi extrémních případů by se to nijak záporně neprojevilo. Jinak je ovšem efekt použití obou synchronizačních pri- mitiv velmi podobný. Není úplně možné říci, které primitivum je z hlediska výkonu efektivnější, jelikož to už záleží na tom, jak jsou tato primitiva v SDL přesně implementována a na jakém stroji aplikace běží (ovšem rozdíly budou jen minimální). Tedy je v zásadě jedno, které se použije. Obzvláště však z důvodu větší srozumitelnosti kódu byl nakonec vybrán semafor.

21 3.2 Inteligence

Počítačem ovládaný hráč musí v průběhu hry (kdykoliv je požádán) samo- statně vykonávat rozhodnutí u fází licitace, výběru hry, flekování a samotné hry (co nést). K tomu se také využívá odhadnutí výsledku hry z karet hráče (respektive protihráče) a odvozování karet v ruce ostatních postupnou vy- lučovací metodou.

3.2.1 Odhad výsledku hry Odhad výsledku hry stanoví, zda je výhra pro každou část (hrovou a sedmo- vou) zadané hry (typ hry, případně barvy trumfů a pomocných) téměř jistá, pravděpodobná nebo téměř vyloučená. Používá se u hráčů či protihráčů, aby věděli, jak flekovat, nebo u hráče při výběru hry, kdy se pak ale ještě musí dle odhadů hra ohodnotit. Toto ohodnocení se provádí pomocí modulu pro ocenění výsledku hry, kterému se dají jednotlivé odhady jako vstup a který stanoví celkovou cenu hry, přičemž jsou zvýhodněny téměř jisté odhady nad jen pravděpodobnými (při oceňování se ta část hry znásobí). Některé hry samozřejmě mají jen jednu část, pak se zbylá ignoruje (a ani se v ocenění neprojeví). Pro uhrání sedmy musí hráč mít sedmu trumfovou a k tomu dostatek prostředků, aby získával štychy (a tedy tím i ten poslední). Za prostředky pro získání štychu je nejlepší brát trumfy a esa. Zvážit se musí i počet ne- trumfových barev, neboť čím jich je více, tím menší je šance včas vytrum- fovat protihráče. Tedy zjednodušeně šanci na uhrání určuje počet trumfů po přičtení es a odečtení počtu barev. Pro hráče jako forhonta pak lze vše posuzovat mírněji. Při odhadování jen hry se sečte počet uhratelných desítek, tedy es a desítek, které jsou buď podložené králem nebo jsou s esem v dané barvě. V každé barvě se také přičítají hlášky. Následně se pak porovná pro odhad počet těchto desítek proti zbylému počtu desítek (protihráčů) a půlce jejich potenciálních hlášek pro pravděpodobnou výhru, respektive všech možných hlášek pro téměř jistý odhad. Předpokladem tohoto je dostatek trumfů, ale to si zajišťuje již odhad sedmy. U kila se hráč rozhoduje dle počtu trumfů a počtu desítek, které mu utíkají (získají je soupeři, počítá se i poslední štych). Hráč musí mít buď čtyřku, kdy mu smí utéct nejvýše tři desítky, nebo dvacku, kdy nejvýše jedna. Hráč by měl mít alespoň čtyři trumfy, aby se nestalo, že mu protihráč bude

22 zabíjet i jinak kryté barvy. Za utíkající desítku se považuje eso a desítka, které hráč nemá, nebo nepodložená desítka bez esa. Utíkající desítky se počítají jen u barev, které hráč má (jinak se bere, že je někdy vezme trumfy, a tak neutečou). Utíkající trumfové se berou jako dvojnásobek, neboť je pravděpodobné, že si na nich namažou jednu z jinak krytých desítek. Sto sedm se získá kombinací postupů u kila a sedmy s drobným zpřísněním sedmy. Pro uhrání dvou sedem hráčem je podstatný počet trumfů a pomocných (a hráč musí od těchto barev mít sedmy). Pakliže jsou nějaké cizí barvy v ruce přítomny, je nejlepší, když se jedná o esa. Protihráči nesmí mít více jak čtyři pomocné, jinak jsou sedmy prohrané. Pakliže mají protihráči čtyři pomocné, může být výhra nanejvýš pravděpodobná (sejdou-li se u jednoho protihráče čtyři, hráč prohraje). Sto a dvě sedmy pak stačí posoudit jako dvě sedmy, kde se navíc zkontroluje, zda hráč uhraje dost desítek (dvě sedmy jsou již natolik přísně hodnocené, že to stačí). U betla a durcha pak hráč zkoumá počet míst, kde ho mohou protihráči ohrozit. Pro betla jsou to všechny karty od barev hráče, které mají protihráči nižší než hráč (výjimkou jsou barvy, kde má hráč šest a více karet a lze to z nich výnosem vytáhnout). Pro durcha naopak karty, které má hráč nižší než protihráči od této barvy, při čemž počet karet protihráčů je vyšší než co z nich může hráč vytahat nejvyššími od této barvy. Protihráč chytá sedmu pokud ji má (ovšem odhaduje ji u samotné sedmy jako výhru jen když nehrozí, že hráč tím zakrývá kilo) nebo pokud má dost trumfů a es. Hra je zkoumána obdobně jako u hráče, může ale i trochu riskovat, když má trháka. U kila protihráč zohledňuje počet trumfů, po- čet trumfových ostrých a počet es. Sto sedm je kombinací předchozích. Dvě sedmy protihráč odhaduje dle počtu trumfů, pomocných, es od těchto barev a es obecně. U sto a dvou sedem pak navíc pro kilo protihráč odhadne dle počtu trumfů a es (nepočítá s pomocnými, neboť neví, zda hráč neblafuje a nechce hrát jen velmi drahé kilo). U betla a durcha pak protihráč od- hady provádí na základě počtu krytých barev (má od této barvy nejnižší, respektive nejvyšší či podložené vysoké karty).

3.2.2 Výběr hry Hráč si vybírá hru tak, že pro všechny možné odhozy do talonu karty ohod- notí pro každou možnou hru. Použití hrubé síly se zde bohužel efektivně zabránit nedá, avšak dostanou se tak srovnatelné výsledky s člověkem, takže

23 lidskost inteligence není příliš narušena. Z odhadu hráče zajímá pouze cel- ková cena (kde již zhodnocena jistota výhry). Vybere tak všechny hry s odhozy, jejichž cena je nejvýhodnější. Tento výběr ještě sníží dle výhodnosti odhozů do talonu. Tím se zlepší šance na výhru, neboť i když by šlo napří- klad uhrát sedmu s pěti trumfy, zatímco jeden trumf je v talonu, bylo by určitě lepší hrát ji se šesti trumfy. Postupně se tedy budou filtrovat všechny možnosti ale jen tak, aby po každém zúžení výběru zbyla alespoň jedna možnost. To tedy znamená, že aplikace těchto filtrů musí být dle jejich pri- ority. První filtr je pro neodhazování sedem, pokud jsou hlášené (to může nastat pokud je pravděpodobná prohra, ovšem někdy i tehdy lze vyhrát a je zbytečné se vzdávat). Další je na neporušování hlášky, když jde o hru. Po- tom následuje filtr na šetření trumfů (co nejméně odhazovat u her, kde jsou trumfy). Pro betla a durcha se pak snaží filtr zbavit co nejvíce nevhodných karet (přebitelné u durcha a nepřebitelné u betla apod.). A nakonec je ve všech typech hry aplikován filtr, který se snaží, aby po odhozu zůstalo hráči co nejméně barev. Ze zbytku možností (co hrát a jak odhodit) se nakonec vybere náhodně.

3.2.3 Flekování Hráč nebo protihráč využijí modulu pro odhad hry a získají tak pravděpo- dobnosti výhry pro hrovou i sedmovou část (u her, kde jen jedna část je druhá pro flekování i odhady ignorována). Každému stupni pravděpodob- nosti je přiřazena konstanta, která určuje, kolikrát chce mít hráč (respektive protihráč) maximálně hru fleknutou.

3.2.4 Licitace Pro zadaný typ hry hráč zkusí pro všechny možnosti, zda by měl až na tento typ hry licitovat. Tento postup se při zjišťování kam až licitovat aplikuje na všechny typy her od nejvyšší po nejnižší (dle tabulky 5.1). Pro licitaci na sedmu stačí mít alespoň čtyři trumfy a sedmu nebo hlášku trumfovou, neboť jde a levnou hru a mohlo by v talonu přijít něco zajímavého. Na kilo by měl mít hráč čtyřku, alespoň čtyři trumfy a neměly by mu utíkat více než tři desítky (počet desítek, které utíkají, se počítá stejně jako v odhadech výsledku hry). U sto sedmi musí hráč splňovat podmínky pro kilo a sedmu mít ani nemusí, neboť ta není drahá a může se to vyplatit. Licitovat na vyšší hry by se mělo jen velmi obezřetně, neboť už je těžší je uhrát. Na betla lze

24 licitovat s nejvýše jednou dírou a s žádnou kartu, která by byla nejvyšší (vyjma případu, kdy má hráč alespoň sedm karet této barvy). Na durch smí hráč licitovat jen když od každé barvy v ruce má eso a zároveň je schopen vytahat všechny karty, které by mu mohly něco přebít. Dvě sedmy se pak licitují dle počtu trumfů a pomocných (a musí ty sedmy mít), při čemž u sta a dvou sedem musí hráč mít navíc i čtyřku a alespoň jednu ostrou od trumfů i pomocných.

3.2.5 Odvozování karet ostatních U cizího hráče (spoluhráče či protihráče) hráč nezná na začátku karty, které má, může ovšem ze svých karet a karet vynesených v průběhu hry postupně zúžovat výběr možných karet v ruce cizího hráče. Je zřejmé, že tento cizí hráč nemůže mít v ruce karty, které má hráč, a ani ty, co již byly neseny. Dále při nedodržení barvy lze vyloučit celou barvu z karet, co může mít, pokud je navíc hrána právě hra s trumfy a on jej zde nezanese, lze vyloučit i celou trumfovou barvu. Stejně tak při dodržení barvy a nepřebití (přestože to má udělat) se ví, že nemá žádnou vyšší kartu. Pak lze z takto získaných poznatků odvozovat informace užitečné pro hráče, který si možné karty cizího hráče hlídá, jako například, zda má cizí hráč danou kartu, barvu, vyšší kartu barvy než zadaná apod.

3.2.6 Co nést Hráč potřebuje rozhodnout, co v daném štychu nést. Na výběr má ze všech karet v jeho ruce, které má umožněné pravidly v daný moment nést (ty mu umí dát přímo štych). Z těch postupnou filtrací vybere ty nejlepší výnosy, odkud pak náhodně jeden vybere. Zohledňovat při nesení karty musí jak pozici ve štychu (tedy kolikátou kartu nese), tak i pozici sebe vůči hráči hrajícímu tuto hru (je-li on ten hráč, je-li protihráč hned za hráčem, či je- li protihráč před hráčem). Dále pak vše samozřejmě závisí na typu hry, i když některá pravidla platí obecně pro více typů her. Aby hra nebyla příliš předvídatelná a svými výnosy počítačem řízení hráči co nejméně prozrazo- vali, za nejnižší, repsektive nejvyšší karty se bere taková skupina karet, mezi nimiž nejsou mezery zaplnitelné kartami, které má někdo jiný, obdobně ja- kékoliv jiné operace na množině karet vracejí opět množinu karet se chtěnou vlastností. Tak se také získá více možností k filtrování a tedy i potenciálně lepších výsledků. Náhodný výběr na konci pak zabrání prozrazení informací

25 navíc o kartách v ruce (kdyby například vždy nesl právě tu jednu nejnižší kartu, respektive nejvyšší, věděl by hned uživatel, že tento hráč určitě nižší, respektive vyšší, kartu nemá). Rozhodnutí, co namazat (tedy zanést ostrou do štychu, který vezme spo- luhráč), probíhá dle pokrytosti barev ostrými (například určitě namaže dříve osamocenou desítku než eso, u kterého neví, kdo má desítku této barvy). Při odmazávání (tedy nesení pokud hráč nemá nesenou barvu ani trumfy) se pak snaží hráč zbavit nepohodlných barev či karet pro daný typ hry, opět je řa- zeno od těch nejvíce nepohodlných k nejméně. Vyjma betla je snaha si u každé barvy nechávat co nejvyšší karty (pokud se ovšem nejedná o ostré při hře, kde jde o desítky, nebo pokud nechce zajistit přebití štychu zrovna). V poslední pozici si již každý může být jistý tím, kdo štych zabíjí. To mimo jiné znamená, že při hře, kde jde o desítky, tam může protihráč svému spoluhráči bez problémů mazat (pokud spoluhráč zabíjí štych). Stejně tak z pozice posledního se naprosto nemusí brát v potaz, jak vysoko nést, už se tím nic ve štychu nezkazí. U betla se zde samozřejmě zbavuje nejvyšších karet. Naopak z pozice druhé nesené karty musí hráč, který se pokouší štych zabít, nést tak vysoko, aby ten za ním již nemohl přebít (aby věděl jak vysoko, použije k tomu odvozování karet toho za ním). V pozici druhé karty štychu také protihráč maže buď, když je za ním spoluhráč, nebo, když je za ním hráč, který nemůže štych přebít. U betla se zde protihráč, když hráč před ním, zbavuje těch nejvyšších karet, pokud je ovšem hráč za ním a mohl by přebíjet, nese co nenižší. Při výnosu (tedy pozice první karty ve štychu) pak hráč musí zvolit i barvu výnosu. U her s trumfy je to pro hráče barva, kterou tahá nejvíce trumfů. Protihráč, který se domnívá, že je to právě on, kdo má být hlavním z dvojice (tedy že on bude chytat hráče na sedmě apod.), vynáší barvu, kterou tahá trumfy ze hráče a nejlépe netahá od spoluhráče, je-li to možné. Naopak protihráč, který není hlavním, nikdy nenese tak, aby tahal trumfy ze spoluhráče, ovšem snaží se je tahat z hráče. Co se týče výšky výnosu, první výnos od této barvy u her o desítky se snaží všichni esem (tím obhlédnou situaci). U betla hráč vynáší jen jednou, a to tak, aby se zbavil jedné z děr. Protihráč u betla, když je za hráčem nese od nejnižších u barev, kterými by hráče mohl chytat, ale, když je před hráčem, pokud vysloveně neví, že hráče chytá, nese tak, aby si jeho spoluhráč (za hráčem) mohl odmazat a případně se dostat k výnosu. Při durchu vždy vynáší první hráč a protihráči jen reagují nesením co

26 nejnižších karet vynesené barvy nebo si odmazávají od barev dle toho, co ještě hráč může mít, a dle kvality krytí barev nejvyššími, respektive vyso- kými kartami, které jsou dostatečně podložené. Ve hrách, které mají sedmovou i hrovou část pak lze mírně poupravo- vat strategii výběru, co nést, dle toho, co je dražší, respektive, o co se má ještě smysl snažit hrát, ale toho se využívá jen málokdy, neboť většinou se postupnou aplikací filtrů podaří dosáhnout vhodného kompromisu.

3.3 Síť

Aby mohla hra běžet i přes síť, je třeba zajistit síťové spojení, zde kon- krétně pomocí TCP soketů. O to se postarají objekty TCPIP spojeni hrac (na straně vzdáleného uživatele) a TCPIP spojeni proxy (na lokální straně). Pak metody vzdáleného uživatele (Sitovy hrac) budou (vzdáleně) volány skrze prostředníka (Sitovy hrac proxy, pojmenovaného ve stylu standard- ních RPC technologií, obdobně jako jeho objekt poskytující spojení). Díky tomu, že vše, co se má zobrazit všem uživatelům jde přes Jadro, tak stačí, aby Jadro přes všechny TCPIP spojeni proxy volání zobrazovacích metod zopakoval na obou vzdálených instancích Jadro. A tak vzdálená grafická prostředí společné věci zobrazují stejně. Sitovy hrac, jakožto potomek třídy Uzivatel, je schopen komunikovat s jeho vlastním grafickým prostředím a tedy dostávat patřičná rozhodnutí od jeho uživatele (která pak odešle po síti jako návratové hodnoty metod na něm vzdáleně volaných). Vše snad bude jasnější z UML diagramu na obrázku 3.3. Vzdálená volání budou implementována dle jednoduchého protokolu, po- staveném nad po síti posílanými pakety. Paket bude obsahovat unikátní ID vygenerované při zahájení série her (kdyby náhodou přišlo co nemá, tak ignorováno), co volá (jednoduchý výčtový typ pro možné metody) a para- metry metody. Návratová hodnota (odpověď), pokud bude třeba, bude v obdobně strukturovaném paketu jen výčtovým typem bude řečeno, že je to odpověď a místo původních parametrů budou následovat data odpovědi. Pa- ket se skládá výhradně z 32 bitových hodnot zapsaných a čtených správně bez ohledu na platformě. Takže zbývá jen zajistit, aby se před odesláním vše správně rozkouskovalo do paketu na nejvýše 32 bitové části a na druhé straně opět z paketu správně složilo.

27 Obrázek 3.3: Asociace jednotlivých objektů při síťové hře

3.4 Struktura

Projekt je rozdělen na několik částí pro větší přehlednost implementace. Zdrojové soubory každé takové části jsou pak ve zvláštním adresáři, jehož název je (až na případnou diakritiku) stejný s názvem části, kterou obsahuje.

3.4.1 GUI Část GUI obsahuje vše, co se týká grafického prostředí. Grafické prostředí musí zobrazovat informace potřebné k rozhodování uživatele při ovládání hry v dané fázi (viz tab. 3.1), ale například i jména všech hráčů, konta apod. Bude obsluhováno ve zvláštním vlákně, čímž bude zajištěna přiměřená ode- zva všem požadavkům. Samotnou správu grafické části aplikace bude mít na starost objekt Gui. Tato správa zahrnuje tištění různých druhů textu, vykreslování obrázků a poskytování možnosti zpětné odezvy uživateli, aby mohl aplikaci ovládat. Fonty použité k tisku budou nataženy do paměti přímo z binárního kódu aplikace. Všechny české texty budou uloženy na jednom místě jako konstanty. Obrázky k tisknutí budou vyobrazení karet.

28 Ty se vystřihnou z nascanovaného snímku skutečných karet, který se na- táhne obdobně jako fonty do paměti z binárního kódu aplikace. Aby se dala poskytnout zpětná vazba, musí být známo, kam uživatel právě kliknul a zda toto místo je zobrazeným textem či kartou, které na kliknutí má reagovat. Dále se pak musí právě v tomto vláknu odchytávat a zpracovávat všechny události. A tedy bude vlákno schopné obsloužit uživatele a grafické prostředí a přitom nemusí komunikovat s vláknem jádra příliš často, což by vedlo ke snížení efektivity. Zmíněná komunikace bude probíhat přes sérii globálních proměnných.

3.4.2 Hra Část Hra má na starost implementaci chodu hry dle všech pravidel lici- tovaného mariáše (viz kap. 5.2). To mimo jiné obnáší řízení chodu hry v jednotlivých fázích popsáných v tabulce 3.1 a přechodu mezi fázemi dle di- agramu na obr. 3.1, což bude mít na starost třída Marias. Aby však bylo pro uživatele možné pozorovat, co se děje, musí se veškeré změny zobrazit i v grafickém prostředí, tam je Marias propaguje přes Jadro. Dále je nutno reprezentovat karty a štych. Jelikož se s nimi bude pracovat na více místech, vyplatí se agregovat co nejvíce funkčnosti přímo do tříd, které je reprezentují, aby byla všude s nimi rovnou k dispozici, než aby se implementovala vícekrát téměř stejně (respektive byla globálně a pletla se i ostatním). Karta bude kromě své hodnoty a barvy schopna říct také svou přebíjecí hodnotu (viz tab. 5.2) v daném typu hry. Stych bude nejen znát v něm zanesené karty, ale také umět říct, které karty může dle pravidel daný hráč právě vynést. Stych bude moct také sám sebe zhodnotit (tedy počet desítek, či porušení podmínky vítězství ve štychu, který představuje), a tedy musí znát i podrobnosti o právě hrané hře. Výhodné také bude oddělit ocenění výsledku hry do samostatnbého modulu, aby mohlo být použito (kromě fáze ocenění hry) i při rozhodování, co je lepší hrát u počítačem řízeného hráče (viz kap. 3.2).

3.4.3 Hráči Část Hráči implementuje všechny typy hráčů. Každý hráč musí vykoná- vat různá rozhodnutí v průběhu hry. Rozhraní pro tato rozhodnutí spolu se seznamem karet (mimo jiné) bude definováno v abstraktní třídě Hrac. Počítačem ovládaný hráč (Pocitac) pak pro tato rozhodnutí bude používat

29 Inteligenci (viz kap. 3.2). Síťový hráč, který bude fungovat jako prostředník vzdálenému uživateli, (Sitovy hrac proxy) pak pošle dotazy a příjme roz- hodnutí přes síť (viz kap. 3.3). Uživatel naopak svá rozhodnutí vloží přes grafické prostředí, tuto komunikaci zajistí abstraktní třída Uzivatel. Toho využije uživatel hrající přes síť (Sitovy hrac) a uživatel hrající lokálně (Do- maci hrac), jediný rozdíl mezi nimi je, že Sitovy hrac pošle svá rozhodnutí přes síť (k Sitovy hrac proxy). Dědění mezi třídami reprezentujícími hráče jsou také vyobrazeny na obr. 3.4.

Obrázek 3.4: Hierarchie hráčů

3.4.4 Inteligence Část Inteligence poskytuje umělou inteligenci počítačem ovládaným hráčům, jak popsáno v kap. 3.2. Modul Licitator řeší, kam až má hráč licitovat. Po vyhrané licitaci vybrat hru a odhodit má na starost modul Co hrat. Jak flekovat vyřeší modul Fleky. A konečně modul Jak nest obstará výnos karet. Moduly Fleky a Co hrat potřebují odhadovat výsledek hry, k čemuž použijí modulu Odhad vysledku. Jak nest naopak bude vyžadovat znalost karet, které mohou ještě v daný moment mít ostatní, což mu umožní modul Jiny hrac.

30 3.4.5 Jádro Část Jádro se skládá jen z modulu Jadro, který má na starost implemen- taci základní třídy aplikace, tedy třídy Jadro. Instance této třídy existuje po celou dobu běhu programu. Jadro spustí vlákno grafického prostředí, vše ini- cializuje a zprostředkovává komunikaci jednotlivých částí aplikace běžících ve vlákně jádra a grafického prostředí, která se týká všech hráčů. Pro každou novou sérii her v sobě vytváří novou instanci třídy Marias (pro řízení chodu her) a seznam hráčů (jejich jména a konta jsou zvlášť v globálních proměn- ných, aby k nim mělo přístup i grafické prostředí). Komunikace vlákna jádra s grafickým prostředím je dělena na tu, která se týká průběhu hry, a je dele- gována skrz instanci třídy Jadro, a na tu, která se týká jen uživatele, a tak jde přímo od instance tohoto hráče. To také zobrazuje UML diagram na obr. 3.2. Jedinou výjimkou tohoto dělení bude řízení chodu hry uživatelem dříve než je jakákoliv hra založena, tedy Menu, kde si komunikaci s uživatelem, který ještě nemá vytvořenu instanci, která by ho reprezentovala, obstará samo Jadro.

3.4.6 Síť Část Síť obsahuje jediný modul TCPIP spojeni, který poskytuje vše popsané v kap. 3.3.

3.4.7 Sync Část Sync opět jen jediným modulem Sync implementuje základní pro- středky pro ulehčení synchronizace, jak popsáno v kap. 3.1, tedy funkce pro aktivní i pasivní čekání a funkce pro práci se semafory.

31 Kapitola 4

SDL

SDL (Simple DirectMedia Layer, [9]) je multiplatformní knihovna poskytu- jící jednoduchý přístup ke grafice, zvuku, myši klávesnici a použití vláken (mimo jiné). Díky své pružnosti a jednoduchosti je velmi oblíbená obzvláště pro tvorbu her, ale hodí se i pro použití v řadě jiných multimediálních apli- kacích. V tomto programu je konkrétně využita verze 1.2.13. Jelikož není její aplikace v tomto projektu zcela triviální, zdá se být dobrým nápadem si nejprve relevantní části podrobněji prostudovat.

4.1 Základní použití

Flag Umožňuje SDL INIT AUDIO Ovládání zvuku SDL INIT CDROM Ovládání CD-Rom SDL INIT JOYSTICK Vstup joysticku SDL INIT TIMER Použití časovačů SDL INIT VIDEO Ovládání grafiky SDL INIT EVERYTHING Všechno výše

Tabulka 4.1: Možnosti inicializace SDL

Knihovnu lze inicializovat pro různá použití (viz tab. 4.1). Inicializuje se funkcí SDL Init, kde lze parametrem specifikovat, které části budou použity. Pro tuto aplikaci bude stačit jen standardní část s grafikou (SDL INIT VIDEO).

32 Funkce SDL CreateThread vytvoří nové vlákno, ve kterém poběží funkce za- daná jako její parametr. Pro joinutí vlákna (čekání na doběhnutí cílového vlákna) slouží SDL WaitThread. Data do aplikace od knihovny jsou posílány pomocí zpráv. Díky tomu je pak možno v programu reagovat na pohyby myši, stisknutí kláves apod. Zprávu (událost) reprezentuje SDL Event, které kromě specifických dat ob- sahují typ události, podle něhož pak lze na událost reagovat, například za- vření okna (SDL QUIT ), stisknutí klávesy (SDL KEYDOWN ), pohyb myši (SDL MOUSEMOTION ) a kliknutí myší (SDL MOUSEBUTTONUP). Vy- jma nativních zpráv lze definovat i vlastní události (typ SDL USEREVENT ). Do fronty událostí lze vložit novou funkcí SDL PushEvent. Pasivně čekat na nově přišlou událost umí funkce SDL WaitEvent, získat ji pak lze funkcí SDL PollEvent.

4.2 Grafika

Základní strukturou pro práci s grafikou je SDL Surface, který představuje bitmapu a drží i další údaje o ní jako například šířku, výšku a hloubku barev. SDL Surface lze funkcí SDL BlitSurface zobrazit na zadané místo do jiného SDL Surface. Konečně obraz okna (respektive celé obrazovky) lze získat pomocí SDL SetVideoMode v podobě SDL Surface a jeho obsah pak zobrazovat funkcí SDL Flip, tedy lze takto plně ovládat, co se zobra- zuje. Na načtení obrázků z nataženého binárního kódu aplikace je použito SDL RWFromMem, z čehož pak SDL LoadBMP RW vytvoří SDL Surface, se kterým již práce byla popsána. Funkce SDL DisplayFormat je pak může optimalizovat pro použití ve formátu, kterým je zobrazován obsah hlavního okna. SDL Surface lze vytvořit i přímo pomocí SDL CreateRGBSurface. Pro uvolnění zdrojů SDL Surface se volá SDL FreeSurface. Pro okopírování jed- noho SDL Surface do druhého lze použít funkce SDL ConvertSurface. Barvy ve formátu RGB jsou reprezentovány strukturami SDL Color, převést je do konkrétní hodnoty pixelu umí SDL MapRGB. Funkcí SDL SetColorKey lze nastavit barvu pixelů SDL Surface, která se zde má chovat jako průhledná.

4.3 Text

Pro práci s textem je použita komponenta SDL TTF ve verzi 2.0.9. Funkcí TTF Init se inicializuje a po skončení práce její zdroje uvolní TTF Quit.

33 Pro načtení fontu, který je v nataženém binárním kódu aplikace, je nutno použít SDL RWFromMem, načež z toho TTF OpenFontRW vytvoří již k tisku použitelný TTF Font. Pro uvolnění zdrojů načteného fontu se volá TTF CloseFont. K výtisku textu z unikódových znaků (a za použití alfa- blendingu, aby písmo lépe vypadalo) slouží TTF RenderUNICODE Blended, barvu specifikuje SDL Color. Tím získáme nové SDL Surface zobrazující text na průhledném pozadí. Funkci TTF SetFontStyle lze použít pro na- stavení fontu na písmo psané tlustě či kurzívou. Aby se stisknuté klávesy mohly překládat rovnou do unikódových znaků, musí ze to nastavit pomocí SDL EnableUNICODE.

4.4 Síť

Pro práci se sítí je využita komponenta SDL Net ve verzi 1.2.7. Inicializuje se funkcí SDLNet Init a své zdroje uvolňuje pomocí SDLNet Quit. Poskytuje standardní TCP sockety TCPsocket. Struktura sloužící pro držení IP adresy (a portu) je IPaddress. Do té se pomocí funkce SDLNet ResolveHost správně (dle protokolu) uloží hodnota IP adresy (NULL pokud má z ní vytvořený socket sloužit pro zahájení komunikace) a portu. Na zadané IPaddress se pak voláním SDLNet TCP Open otevře nový socket. Pokud byla zadaná ad- resa v IPaddress skutečná, tak tento socket je propojený a již ho lze použít pro komunikaci dle protokolu TCP/IP. Jinak funkcí SDLNet TCP Accept ze socketu, který měl při vytváření v IPaddress jako adresu NULL a tedy na svém portu naslouchá pro pokusy o spojení, lze získávat nové propojený sockety se vzdálenými stroji, které se (funkcí SDLNet TCP Open na IPad- dress s adresou tohoto stroje a portem, kde stroj naslouchá) o spojení po- koušely. Na propojeném socketu pak lze funkcí SDLNet TCP Send odesílat data po síti (specifikuje se ještě buffer a délka dat v něm) a funkcí SDL- Net TCP Recv data přijímat (specifikuje se cílový buffer a maximální veli- kost dat, která se smí přijmout). Pro pasivní čekání na příjem dat ze soketů slouží SDLNet SocketSet, což je struktura, kam se přidá libovolné množství socketů a funkcí SDLNet CheckSockets se pak pasivně čeká na příchozí data po zadanou dobu. Tato struktura se vytváří pomocí SDLNet AllocSocketSet (kde se zadá, pro kolik socketů má sloužit) a její zdroje se uvolňují funkcí SDLNet FreeSocketSet. Sockety se zavírají voláním SDLNet TCP Close.

34 4.5 Umístění

Knihovny pro vývoj se nachází přímo v adresáři projektu (v SDL-1.2.13, SDL net-1.2.7 a SDL ttf-2.0.9) a jsou přes vlastnosti projektu Visual Stu- dia přímo do projektu nalinkovány. V adresářích debug a release jsou pak uživatelská dll, která jsou potřeba pro spuštění aplikace.

35 Kapitola 5

Uživatelská dokumentace

5.1 Nároky

Aplikaci lze spustit na Windows XP nebo novějších a pro svůj chod potře- buje knihovny SDL. Konkrétně verze SDL 1.2.13, SDL net 1.2.7 a SDL ttf 2.0.9 (pozor, skládá se z několika dll) nebo novější. Pro co nejlepší chod je samozřejmě doporučeno mít nejnovější verzi knihoven SDL (mohou v sobě mít řadu vylepšení a urychlení). Z hlediska hardware pak stačí jakýkoliv stroj schopný zobrazit rozlišení alespoň 1240 na 768. Toto rozlišení je zapo- třebí, aby zobrazené karty byly dostatečně kvalitní a snadno rozpoznatelné (a tedy neubíraly na hratelnosti). Vytížení procesoru a paměťová náročnost je tak nízká, že pro ni nemá smysl klást nároky. Na disku pak zabere hra méně než 2 MB.

5.2 Pravidla

Tři hráči se po jednom ve všech činnostech střídají ve směru hodinových ručiček. Jeden rozdává, za ním je forhont a třetímu hráči se říká zadák. Toto se po každé hře posune. Rozdává se od forhonta po pěti kartách, pak dvě do talonu, načež opět od forhonta po pěti. Tedy každý má na začátku deset karet. Následuje licitace, kde se postupným ptaním vzestupně dle tab. 5.1 mezi sebou hráči dozvědí, kdo bude minimálně co hrát. Tázající se ptá až do nejvyšší hry, kterou má, nebo dokud mu odpovídající neřekne pass. První se ptá zadák forhonta. Pokud se již zadák nechce ptát dále, ptá se rozdávající

36 forhonta, jinak forhont passoval a dále odpovídá zadákovi rozdávající. Tak získáme vítěze licitace a vylicitovanou hru, kterou je ta, na niž se naposled ptal či odpověděl, že ji má. Pakliže se zadák ani rozdávající nechtěli na nic ptát, má forhont možnost buď hrát (vylicitovanou hrou je pak ) a nebo hru ukončit.

Pořadí Typ hry 1. sedma 2. sedma lepší 3. kilo 4. kilo lepší 5. sto sedm 6. sto sedm lepších 7. betl 8. durch 9. dvě sedmy 10. dvě sedmy lepší 11. sto a dvě sedmy 12. sto a dvě sedmy lepší

Tabulka 5.1: Pořadí typů her pro licitaci

Pořadí Betl, durch, dvě sedmy (a lepší) Ostatní typy her 1. sedmička sedmička 2. osmička osmička 3. devítka devítka 4. desítka spodek 5. spodek svršek 6. svršek král 7. král desítka 8. eso eso

Tabulka 5.2: Přebíjecí pořadí karet (sedmička nejnižší karta, eso nejvyšší)

Vítěz licitace pak obdrží talon a musí si vybrat vylicitovanou, či dle tab. 5.1 vyšší hru. Pokud to typ hry vyžaduje, musí zvolit i barvu trumfů (u

37 lepších her je barva napevno daná jako červená) a pomocných. Poté hráč odhodí talon, při čemž pouze u betla, durcha, dvou sedem a dvou sedem lepších smí dávat do talonu desítky a esa (u těchto her o uhrané desítky totiž nejde). Typ hry spolu s případným počtem trumfů v talonu je pak oznámen všem. Ve fázi flekování pak lze navyšovat cenu hry. Flekovat se dá na sedmovou i hrovou část hry (vyjma betla s durchem, kde je jen hrová část hry, a dvou sedem a dvou sedem lepších, kde je jen sedmová část hry). Flekuje se tak dlouho pro každou část hry, až než jedna strana odmítne na tuto část flekovat dále. První může flekovat protihráč umístěný přímo za hráčem, načež se všichni ve směru hodinových ručiček střídají a to tak dlouho, dokud již není možné na nic flekovat, tedy pro všechny části hry již buď hráč nebo oba protihráči odmítli flekovat. Z důvodu nízké ceny sedmy se v případě situace, kdy nikdo nic neflekne nebo je jen fleklá hra jednou, nehraje a protihráči uhradí hráčovi částku dle tab. 5.3. Lepší sedma (sedma, kde trumfy jsou červené), ostatně jako všechny hry s červenými trumfy, má částku k úhradě dvojnásobnou.

Případ Ocenění sedma, nefleknuto nic 0,3Kč sedma, fleklá jen jednou hra zadarmo

Tabulka 5.3: Ohodnocení pro hry, které nemá význam hrát

Vyjma betla a durcha, kdy první vynáší přímo hráč, který hru hraje (dále jen hráč), vynáší nejdříve vždy forhont. Při hlášené sedmě či dvou sedmách smí hráč nést sedmu trumfovou až v posledním štychu (respektive předposledním u pomocné), pakliže k tomu není pravidly jinak donucen. Štych, ve kterém již byla nesena karta trumfové barvy (trumf) lze zabít jen vyšším (dle tab. 5.2) trumfem. U typů her, kde nejsou trumfy jsou všechny barvy netrumfové, je předchozí pravidlo zbytečné. Štych dosud bez trumfů může být zabit jen kartou vyšší (dle tab. 5.2) než všechny v tomto štychu vynesené karty od stejné barvy nebo trumfem. Každý je povinen dodržovat barvu první vynesené karty štychu, pokud od dané barvy má alespoň jednu kartu, jinak musí nést trumfy, nemá-li však ani trumfy, může nést libovolnou jinou barvu. Při nesení trumfů je třeba, pokud možno, přebít nejvyšší ve štychu již vynesený trumf. Při dodržení (netrumfové) barvy u štychu, který doposud nebyl přebit trumfem, je také povinné, pakliže je to možné, přebíjet.

38 Ten, kdo zanesl poslední kartu, která zabijí štych (první karta brána, že také zatím zabíjí štych), tento štych po jeho odehrání vezme, při čemž v dalším kole vynáší. U betla má hráč za úkol neuhrát (nevzít) žádný štych, u durcha vzít všechny štychy a u dvou sedem (respektive dvou sedem lepších) vzít před- poslední štych sedmou pomocnou a poslední štych sedmou trumfovou. Ne- dodržením těchto podmínek, případně neschopností je splnit, hra končí (a hráč prohrává), jinak je hra dohrána do konce a vyhrává hráč. Ostatní hry se dohrávají až do konce a dělí se na dvě části, a to sedmovou a hrovou. V sedmové části u sedmy a sto sedmi (respektive lepších) se snaží hráč uhrát poslední štych sedmou trumfovou, pokud se mu to nepovede, tuto část hry prohrává. Dále je možné uhrát tichou sedmu, kterou může uhrát obdobně protihráč či hráč, když ji nehlásil (tedy u kila, respektive kila lepšího). Tichá sedma se počítá zcela zvlášť od hlášené sedmy a strana, která ji uhrála bude vyplacena stranou opačnou. Pakliže hráč bez nahlášené sedmy či protihráč zanese sedmu trumfovou v posledním štychu a kdokoliv jiný bere tento štych, jedná se o sedmu zabitou, kterou pak musí uhradit postižená strana. U sta a dvou sedem (respektive lepších) musí hráč zabít předposlední štych sedmou od pomocné barvy a poslední štych sedmou trumfové barvy, nepovede-li se mu to, tuto část hry prohrává. U sta a dvou sedem (respektive lepších) se na tichou ani zabitou sedmu nehraje. V části hrové jde o počet uhraných desítek. Za každou kartu hodnoty desítka či eso ve štychu, který zabije, získá daná strana desítku. Za každou dvojici král a svršek od stejné netrumfové barvy získává strana dvě desítky a od trumfové barvy čtyři desítky, takovéto dvojici se říká hláška. Hláška se hlásí všem během hry při výnosu první z jejích karet. Strana, která zabíjí poslední štych získává jednu desítku. U sedmy a sedmy lepší se hráč snaží uhrát více desítek než protihráči, aby vyhrál, pokud se ovšem jedné straně podaří uhrát alespoň deset desítek, jedná se o tiché kilo. U kila, sto sedmi, sta a dvou sedem, respektive lepších se hráč zavazuje, že uhraje alespoň deset desítek s použitím jen jedné hlášky.

5.3 Ohodnocení

Ocenění hry se řídí tabulkou 5.4. Každý flek na hru zdvojnásobí cenu hrové části hry. Stejně tak každý flek na sedmu zdvojnásobí cenu sedmové části hry, nikoliv však tiché sedmy (proti, jiná p). Betl a durch v tomto smyslu mají jen hrovou část, zatímco dvě sedmy a dvě sedmy lepší pouze sedmovou.

39 Tiché kilo pouze zdvojnásobí cenu hrové části. U libovolného uhraného kila (tichého i nahlášeného) každá desítka navíc znamená zdvojnásobení ceny. Obdobně u neuhraného nahlášeného kila (u kila, sto sedmi, sta a dvou sedem, respektive lepších) každá chybějící desítka do deseti desítek s použitím jen jedné hlášky, k čemuž se ovšem přičtou hodnoty všech hlášek protihráčů. sečtením cen hrové a sedmové části hry získáme celkovou částku, kterou pak platí oba protihráči hráčovi, respektive hráč protihráčům. Pakliže hra má trumfy a jsou červené (lepší), tak se částka zdvojnásobí. Maximální částka pro jednu hru je 100Kč.

Uhráno Ocenění hra 0,1Kč sedma 0,2Kč kilo 0,4Kč betl 1,5Kč durch 3,0Kč dvě sedmy 4,0Kč tichá sedma 0,1Kč

Tabulka 5.4: Ohodnocení

5.4 Ovládání

Ovládání hry je velmi intuitivní a lze k němu využít jak myši, tak klávesnice. V průběhu hry musí uživatel vykonávat různá rozhodnutí, ať už se jedná o odpověď na položenou otázku, či vybrání karty. V GUI jsou dva typy tlačí- tek. Jedním jsou odpovědi na položenou otázku, které jsou modré s bílým nápisem odpovědi. A druhým jsou přímo obrázky karet. Tlačítka, ze kterých může uživatel vybírat jsou vždy orámována tmavě zelenou barvou, vyjma toho vybraného, které je orámováno světle zeleně. Stisknout tlačítko lze buď klávesou ENTER, kdy je stisknuto právě to vybrané (orámované světle ze- leně), nebo myší kliknutím na něj. Výběr tlačítka lze změnit buď šipkami nebo najetím myši (nově vybrané tlačítko pak bude orámováno světle ze- leně). Při alespoň elementární znalosti pravidel (viz kap. 5.2) by uživatel neměl mít žádný problém hru ovládat, neboť při každém kroku je mu řečeno co má dělat (ať už instrukcí či položením dotazu, na který má odpovědět).

40 V hlavním Menu (viz obr. 5.1) lze pomocí tlačítek vybrat, zda ukon- čit aplikaci (Konec), zda založit novou sérii her proti počítačem ovládaným hráčům (Normální hra) či proti lidským hráčům po síti (Založ síťovou hru), nebo, zda vstoupit do již založené síťové hry (Vstup do síťové hry). Ve všech případech, kdy uživatel neukončil aplikaci, pak musí napsat jméno, pod kte- rým chce hrát (maximálně 15 znaků) a dát ENTER. V případě vstupu do již založené síťové hry je pak ještě třeba stejným způsobem napsat IP ad- resu stroje, kde byla hra založena. Dojde-li k jakékoliv chybě při síťové hře, je aplikace vrácena zpět do hlavního Menu a vespod je červenou barvou oznámeno proč (například nastane při zadání neplatné adresy či přerušení spojení).

Obrázek 5.1: Hlavní Menu

Pokud vyhraje uživatel licitaci, musí vybrat hru, kterou chce hrát, a od- hodit talon. Při výběru hry (viz obr. 5.2) uživatel stiskne tlačítko, jehož popisem je typ hry, který chce nahlásit. Pokud to typ hry vyžaduje, je třeba ještě obdobným způsobem zvolit trumfovou a případně i pomocnou barvu. Po té následuje výběr talonu, kdy má uživatel za úkol vybrat dvě karty k odhození do talonu. Vybírá je ze spodních karet (jejich stisknutím), které představují karty v ruce hráče, a to pouze z těch, které lze odhodit dle pra- videl (zbylé nejsou tlačítky, tedy na kliknutí ani výběr klávesnicí nereagují). Vybraná karta do talonu se pak přesune ze spodních karet výše do vybra-

41 Obrázek 5.2: Výběr hry ných karet. V případě, že si uživatel výběr karty talonu rozmyslí, může ji jejím stisknutím ještě vrátit zpět do karet ruky. V momentě, kdy již jsou obě karty do talonu vybrány, objeví se i tlačítko Odhoď! (viz obr. 5.3). Po stisknutí tlačítka Odhoď! je pak talon odhozen a zvolená hra je nahlášena ostatním hráčům (a již nelze nic vracet zpět). Rozehranou sérii her (normální i síťovou) lze kdykoliv přerušit stisknu- tím klávesy ESC. Poté bude uživatel požádán o potvrzení (viz obr. 5.4). V případě, že nebude chtít ukončit sérii her (dá Ne), bude hra navrácena zpět do stavu před stisknutím klávesy ESC, jinak (dá Ano) se vše ukončí a vrátí do hlavního Menu.

42 Obrázek 5.3: Odhoz talonu

Obrázek 5.4: Potvrzení ukončeni

43 Kapitola 6

Programátorská dokumentace

V následujícím textu je abecedně setříděný popis struktury, oboru činnosti, vzájemných vztahů a fungování modulů, ze kterých se program skládá. Tedy pouze popisuje způsob implementace Návrhu (kap. 3), kde je popsána apli- kace s větším nadhledem.

6.1 Init

Init je soubor obsahující sdílený kód a je vkládán do všech modulů. Vyjma deklarací některých objektů, obsahuje i všechny použité výjimky. Definovány jsou zde základní konstanty, výčtové typy (barvy, hodnoty, pozice hráčů), pole z hodnot těchto výčtových typů (a přímo po spuštění aplikace si z nich udělá vectory pro snadnější procházení) a několik struktur použitých na více místech (Hra, Hlaska a Vylicitovano). Hra určuje typ hry a barvy, ve kterých se vše odehrává, Hlaska obsahuje, kdo, jaké barvy a jaký typ hlášky měl a Vylicitovano spojuje hráče s vylicitovanou hrou. Také je zde funkce Modulo3, která je modulem 3 pro potřeby pohybu po poli hráčů různými směry (je-li třeba pro daného hráče zjistit, kdo hraje jako další, nebo, kdo hrál předtím). Výjimky se dělí na fatální, které jsou způsobeny neočekávanou chybou apli- kace, a ty, které má smysl odchytávat. Tam patří Exception Konec serie her (vyvolána klávesou ESC) a Exception TCPIP spojeni (způsobena, když pře- rušeno spojení v síťové hře), po kterých se ukončit právě rozehraná série her. Zvláštním případem je Exception Konec, která korektně ukončí aplikaci. K ukončování je výjimek využito pro jednoduché použití i v hlubším zanoření v kódu.

44 6.2 GUI

6.2.1 Ceske hlasky V modulu Ceske hlasky jsou umístěny veškeré texty v češtině, které se po- užívají v grafickém prostředí, a to včetně interpunkce. Za použití češtiny ovšem musíme zaplatit tím, že místo se standardními stringy musíme praco- vat s poli wchar t, jež jsou 16 bitovou reprezentací unikódových znaků. Na- chází se zde také funkce usnadňující práci při vytváření českých textů pro grafické prostředí. Mezi ně patří převodní funkce, vracející korektní český název pro daný typ (Vrat nazev hry, Vrat nazev barvy, Vrat otazku na hru, Vrat odpoved licitace a Preved bool). Nedílnou součástí jsou funkce pro zápis částky z počtu desetníků (Zapis castku) a funkce pro konkatenaci českých ře- tězců (Prikopiruj ). A dále ještě funkce použité pro výtisk výsledku hry (Pri- pis pocet fleku pro zhodnoceni a ceny, Zapis vysledek hry a Zapis vysledek kila), které ze zadaných údajů vytvoří český text.

6.2.2 Gui Grafické prostředí a vše, co se něj týká se nachází v modulu Gui. V novém vlákně (spuštěném z Jadro funkcí Run Gui) je vytvořena instance třídy Gui. Již v jejím konstruktoru vznikne a nastaví se okno aplikace, inicializují se všechny potřebné součásti SDL a načtou se fonty a obrázky. Obrázky karet jsou všechny v jediném souboru, pro práci s nimi si stačí pouze poznamenat souřadnice oblastí, kde se jaká karta v obrázku vyskytuje do vectoru ob- razky karet ve formě struktur Obrazek karty. Struktura Obrazek karty ob- sahuje instanci třídy Karta (reprezentující kartu) a strukturu SDL Rect, jež SDL využívá pro popis souřadnic nebo polohy a tvaru obdélníkové oblasti, tedy pravě i obrázku karty). Samotný obrázek je uložen v binární podobě v souboru Obrazky.h, odkud jej umí SDL načíst přímo z paměti pomocí metody SDL RWFromMem. Odtud to již převezmou metody RW ops, které pracují přímo s pamětí a které se od normálních metod pro načítání ob- rázků ze souborů liší právě příponou rw. Dokonce jsou RW ops součástí implementace těchto normálních metod. Konkrétně je zde použita metoda SDL LoadBMP RW, která vytvoří z obrázku SDL Surface, tedy strukturu, kterou již lze přímo zobrazit na obrazovku (či její část), případně něco zob- razit do ní. Obdobně jsou načteny fonty knihovnou SDL ttf a z nich pak vy- tvořeny již konkrétní instance TTF Font písem daných velikostí. Z obrázku karet vytvořené SDL Surface se ještě navíc metodou SDL DisplayFormat

45 optimalizuje pro použití ve formátu, kterým je zobrazován obsah hlavního okna. Metodou Run se pak spustí hlavní cyklus Gui, který je přerušen, až když je hodnota globální proměnné quit G false, touto proměnnou lze i od- sud přerušit běh jádra programu. V tomto cyklu se nejprve pasivně čeká za pomoci SDL WaitEvent na další došlou zprávu (resp. nastanutí udá- losti), načež se v dalším cyklu metodou SDL PollEvent zpracují všechny relevantní zprávy, které se získají. Tím, že zprávy jsou zpracovávány ve vnitřním cyklu ihned a ne přes pasivní čekání, které nereaguje tak hbitě, se velmi urychlí reakce na příchozí zprávy, obzvláště s ohledem na fakt, že události většinou nastávají ve větším počtu najednou. Pro Gui jsou zajímavé z nativních zpráv jen SDL QUIT (zavření okna uživatelem), SDL KEYUP a SDL MOUSEBUTTONUP. Další takovou zprávou je SDL USEREVENT, kterou využívá jádro pro komunikaci s Gui. Zavření okna stačí obsloužit tak, že se za quit G false. Stisknutí kláves se hlídá pro přerušení (Esc) a nebo pro psaní při přijímání vstupu. Při kliknutí myši se musí zkontrolovat, zda se na něco nekliknulo, tedy se musí projít seznam všech klikatelných objektů a případně patřičně reagovat. Klikatelné objekty jsou reprezentovány potomky abstraktní třídy Clic- kable object, ta obsahuje informace o tom, kde na ploše se objekt nachází (pomocí SDL Rect) a odkaz na instanci Gui, aby mohla vyvolat patřičnou reakci při kliknutí na ni. Pro účely ovládání klávesnicí je navíc vždy jedno z tlačítek vybrané a zvýrazněné. Najetím myši na jiné tlačítko se výběr pře- sune na něj. Stisknutím šipek se dá posouvat mezi tlačítky zpět a vpřed dle jejich pořadí v seznamu všech tlačítek. Stisk klávesy ENTER, pokud je zrovna některé tlačítko vybráno, způsobí to samé jako kliknutí na něj. Me- tody má Ukazuje sem souradnice na poznání, zda vstupní souřadnice uka- zuje do plochy, která jí náleží a Klikni, která je virtuální a obstarává různou reakci dle toho, na co se kliklo. Klikat lze buď na text (resp. odpověď, re- prezentovanou třídou Clickable odpoved) nebo na kartu (reprezentovánou třídou Clickable karta). Seznamem platných tlačítek (Clickable object*) je uložen jako vector klikatelne a při zpracování zprávy zvednutí tlačítka myši se v něm hledá, na co uživatel kliknul. Tím je umožněno uživateli reagovat na položené dotazy tak, že vybere jednu z nabízených odpovědí (respek- tive karet), které jsou ve skutečnosti zaznamenány jako Clickable odpoved (respektive Clickable karta). Ty pak nechají reakci na Gui, které dle svých stavových proměnných ví, kam má zapsat index vybrané odpovědi (respek- tive karty) a odpoví tak jádru na dotaz.

46 Synchronizace, jak je popsána v kap. 3.1, je implementována SDL semafo- rem gui semafor G a booleanem gui zpracovani zahajeno G (použitým jako signál, že obdržena zpráva od jádra a GUI prošlo semaforem). Pro zprávy od jádra je použito SDL USEREVENT, kde se dále specifikuje (.user.code) typ zprávy hodnotami výčtového typu Zprava gui. Od jádra přichází jak po- žadavky přímo s domácím hráčem, tak informace z Jadro (viz kap. 3.4.5). Jelikož ne na každou zprávu lze reagovat jen jednorázovým zobrazením, které pak zmizí, je třeba si pamatovat, co zobrazovat. K tomu Gui slouží stavové atributy prijem vstupu , zobraz karty atd. Data pro zobrazení se berou z globálních proměnných, které vyplnilo jádro před odesláním zprávy. Při každé relevantní změně se zobraz dá na true, což zapříčiní projevení se změny do okna aplikace. Přednost ve zobrazení (tedy má-li více stavo- vých atributů pro zobrazení hodnotu true) mají požadavky domácího hráče, jemuž GUI slouží k ovládání hry. Až po té se zobrazuje dle požadavků cho- dících přes Jadro. Například příjem vstupu bude probíhat po celou dobu, kdy je prijem vstupu true, tam se tato hodnota dostane přijetím zprávy s kódem GUI PRIJEM VSTUPU načež se projde semaforem gui semafor G a gui zpracovani zahajeno G se dá na true. A dokud je prijem vstupu true, se bude zobrazovat jen příjem vstupu, po stisknutí písmene se přidá onen znak do pole vstup G a po stisku klávesy ENTER se pak do prijem vstupu dá false. Pak se teprve probudí jádro (zvednutím semaforu) a to si pak může zadaný vstup zpracovat. Aby mohlo Gui všechny tyto činnosti zajišťovat, musí k tomu umět vy- kreslovat text (daný konstantami wchar t* v modulu Ceske hlasky). Na to slouží metody začínající názvem Zobraz text, které dokáží zobrazit text buď na místo určené souřadnicí nebo s ohledem na velikost textu. Tím lze pak zobrazit text v dané výšce v dané vzdálenosti od levého okraje, od pravého okraje či aby byl text přesně uprostřed (vzdálenost od obou okrajů stejná). Na jejich vstupu pak je onen text, barva, specifikace pozice dle typu me- tody a pak, zda má být text napsán větším fontem. Tisk využívá metody Vytvor obrazek textu, která pomocí funkce TTF RenderUNICODE Blended (používající alfa blending) pro daný font a barvu získá z textu SDL Surface a vrátí ho. Ten pak metody tisku mohou funkcí SDL BlitSurface zobrazit do hlavního okna a zároveň SDL Surface vrátí, jelikož je z něj ještě možné získat dodatečné informace jako například velikost (hodí se pro tvorbu Clic- kable odpoved). Kromě textu je třeba umět zobrazit i obrázky karet. K to- muto účelu se využívá Zobraz kartu, která získá umístění (SDL Rect) dané karty funkcí Vrat kde vystrihnout obrazek karty v načteném obrázku všech

47 karet a SDL BlitSurface pak požadovanou část obrázku (tj. onu kartu) zob- razí na cílové místo v hlavním okně. Ostatní pak již jen těchto metod v kombinaci se zadanými vzdálenostmi, které určují, kam co patří, využívají dle stavových proměnných zobrazení. Rozehranou sérii her lze kdykoliv přerušit stiskem klávesy ESC. To způ- sobí uložení obrazovky a zobrazení otázky, zda chce uživatel skutečně končit. Řešeno je to tak, že se po takovém přerušení odchytávají všechny události vyjma naprostého konce hry. Pomocí pohybů myši, klikání a kláves se ovlá- dají tlačítka odpovědí jako normálně. Přijde-li mezitím uživatelská událost, uloží se. V případě pokračování se obnoví obrazovka do původní pozice a případně se zpracuje uložená uživatelská událost. Za zmínku ještě stojí metody Zobraz karty hrace a Zobraz talon, které nejenže na daná místa zobrazí seznamy karet prohlizene karty a talon , ale, pokud požadováno (tedy voláno s true), rovnou i vrátí seznam z nich vytvo- řených Clickable karta, které pak lze využít jako tlačítka. Velmi používaná je metoda Zobraz jmena konta hru, která zobrazí standardní podklad pro hrací prostředí dle stavu hry (jména hráčů, a, pokud požadováno, i jejich konta a právě hranou hru). Zobraz stych zobrazující jen zatím odehrané karty štychu na správná místa dle toho, kdo je hrál se pak používá při samotném prů- běhu hry. A metoda Zobraz co rekl zobrazující u zadaného hráče text, který má hráč říct, slouží pro veškerou komunikaci mezi hráči ve hře. Některé zobrazovací metody jsou navíc přetíženy, aby místo na obrazovku zobrazo- valy na zadaný SDL Surface. Toho se pak za pomoci zprůhlednění pixelů v pozadí povrchu dá využít ke skládání několika SDL Surface do jednoho výsledného. Například při tvorbě otázek hráči se nejdříve vytiskne do ved- lejšího SDL Surface text otázky a tlačítka s odpověďmi, dle jejich rozměrů se zobrazí obal i s pozadím na obrazovku (Obal otazku), aby se pak tímto SDL Surface s průhledným pozadím obal překryl (a tedy celkově vznikla obalená otázka se zachovaným původním pozadím obsahu okna).

6.3 Hra

6.3.1 Cenik Modul Cenik slouží k ocenění výsledku odehrané hry. Díky tomu, že se jako vstup nedávají přímo odehrané štychy, ale jen z nich odvozené informace, je možné modul použít i na odhadnutý výsledek hry. Toho pak využívá Co hrat (kap. 6.5.1) při výběru hry, kterou chce počítačem ovládaný hráč hrát. Kon-

48 struktoru třídy Cenik zadáme typ hry (sedma, kilo apod.), počet fleků na hru či kilo, počet fleků na sedmu či sedmy, zda je hra lepší (trumfy jsou červené), počet desítek uhraných hráčem, počet desítek v hláškách hráče, zda měl hráč čtyřicítku, počet desítek protihráčů, co bylo ve hře uhráno (sedma nakonec či proti, betl apod.), zda byla hráčovi zabita sedma a zda byla protihráčům zabit sedma. To vše z pohledu hráče, který hru hrál. Na takto vytvořeném objektu Cenik pak lze zavolat metodu Ocen, která vrátí částku, kterou hráč vyhrál (nezáporná) či prohrál (záporná). Modul si for- mou konstant pamatuje ceny jednotlivých her vůči základu (dle tab. 5.4), kterým je zde, ale i jinde v programu desetník. Proto také částka, která je vrácena je počtem desetníků, což umožňuje držet se celých čísel a získat tak rychlost i přesnost.

6.3.2 Karta Karta je zkrátka třída, která smí říct svou hodnotu (Vrat hodnotu) a barvu (Vrat barvu), ale nesmí je měnit. Dále obsahuje metodu Vrat prebijeci hodnotu, která na základě hodnoty barvy a informace na vstupu, zda má být desítka řazena nad krále nebo pod něj, odvodí její přebíjecí hodnotu. Přebíjecí hod- nota je integer od 1 do 8 (a 0 pro neznámou hodnotu). Karty seřazené dle svých přebíjecích hodnot (se správným umístěním desítky, viz tab. 5.2) vracejí nepřerušenou posloupnost přebíjecích hodnot, čehož se v modulech simulujících inteligenci počítačem ovládaného hráče využívá. Dále jsou zde k dispozici užitečné globální funkce pro práci s vectorem karet jako například Kolik ma vector od barvy, Obsahuje vector kartu, Se- rad vector karet (se zadaným údajem o umístění desítky) apod.

6.3.3 Marias Marias má na starosti řízení chodu samotných her (viz diagram na obr. 3.1). Vytvoří jej Jadro, při čemž mu dá i odkaz na sebe, aby mohl Marias komunikovat s domácím hráčem v GUI (Menu, hlášky a vyhodnocení her). Jednou z jeho základních povinností je starat se o balík (Balik ), talon (ta- lon ) a distribuci karet obecně (např. tedy i odehrané štychy v Stychy ). Balík je jednou na začátku náhodně promíchán metodou Promichej balik, náhodné snímnutí, které nastává po každé hře obstará Snimni balik. Pevně stanoveno už je skládání karet (Sloz balik) a rozdání karet z balíku (Roz- dej ), tehdy si také zapamatuje, kdo je forhont jeho unikátním indexem v

49 poli hráčů (forhont ). Dále je Marias schopen metodou Vyhodnot vyhod- notit právě odehranou hru využitím modulu Cenik. Pro tento účel si také pamatuje, kolik padlo jakých fleků (fleku hra a fleku sedma ). Průběh hry je zahájen metodou Spust hru. Fázi licitace obstará metoda Licitace (po níž je případně předán talon výherci metodou Predej talon) a fází flekování zařídí metoda Flekovani. Dle pravidel může hra skončit už u licitace (nikdo nic ne- chce) a flekování (málo fleků u sedmy). Následuje hraní (Odehraj hru), kdy je po deset štychů postupně každý vyzván, aby do tohoto štychu zanesl. Dle typu hry první štych vynáší buď forhont, nebo ten, co tu hru hraje, další štych již vynáší ten, co zabil štych před tím. Některé hry mohou skončit z důvodu chycení soupeře dříve. Po vyhodnocení (metodou Vyhodnot) hry pak Marias provede finanční vyrovnání (Predani ohodnoceni), v němž se zároveň zeptá, zda se má pokračovat, a pokud ano, hraje se další hra, jinak se vrátí zpět hlavní Menu.

6.3.4 Stych Štych je reprezentován třídou Stych, která nejen že drží v něm zanesené karty, ale umí i zadanému hráčovi říct, co smí dle pravidel do tohoto štychu vynést (metodou Co muze hrat). Štych je také schopen se sám vyhodnotit (Vyhodnot). Aby mohl štych vědět, co lze zanést, musí mít informace o hře a jejím stavu. Ty jsou předány v konstruktoru (co se hraje, kdo to hraje, kdo jej vynesl, jestli má jít sedma nebo sedmy nakonec a zda nejsou sedma či sedmy již prohrané). Vyhodnocením štychu získáme ve struktuře Vysledek stychu, kdo jej vzal, kolik je v něm desítek, seznam zanesených hlášek a zda způsobil tento štych prohru sedmy či sedem. Seznam hlášek je pouze platný, dokud se neodehraje další štych, neboť musí zkontrolovat, zda má i druhou půlku hlášky. Hlášky jsou proto z tohoto seznamu zapisovány již během hry, kdy to zároveň potřebuje vědět Gui, aby je mohl zahlásit (provádí se přes Jadro).

6.4 Hráči

6.4.1 Hrac Modul Hrac implementuje všechny typy tříd hráčů, hierarchie dědičnosti viz obr. 6.1. Abstraktní třídě Hrac, stejně jako i jejím potomkům, stačí v konstruktoru předat jméno a odkaz na Jadro (aby mohl hráč komunikovat s okolím, když třeba). V jádru hry je pak pole všech hráčů, kam musí být

50 každý aktivní hráč zařazen. Index daného hráče z tohoto pole slouží jako jeho jednoznačná identifikace (a to i přes síť), která je mu přidělena ihned po přidání do tohoto pole. Index hráče spravují metody Vrat index a Za- dej index. Jméno hráče je již od jeho vzniku konstantní a pouze jej můžeme získat zavoláním Vrat jmeno, nicméně je zde spíše jen pro ladící účely, ne- boť jména a konta hráčů jsou zvlášť v globálních polích, aby k nim mělo přístup i grafické prostředí. Hráčovy karty a informace o nich jsou přístupné metodami Vrat karty (vrátí vector všech jeho karet), Serad karty (seřadí karty, dle volby buď s desítkou nad králem nebo pod ním), Prijmi kartu (přidání karty do seznamu karet), Zahod karty (zbaví se všech karet), Za- hod kartu (zbaví se konkrétní karty, hodí výjimku, když tuto kartu nemá), Ma kartu (vrátí, zda má tuto kartu), Kolik ma karet barvy (poskytne po- čet vlastněných karet zadané barvy), Ma vyssi dane barvy (vrátí, zda má kartu s vyšší přebíjecí hodnotou od této barvy, pakliže je desítka brána nad nebo pod králem) a Nema karty (zda nemá hráč již žádné karty). Dále také umí komunikovat s GUI přes Jadro (a to se všemi GUI najednou, po- kud se jedná o síťovou hru). Jednotlivé metody pouze volají ty z Jadro, jejichž princip práce je již ukázán v popisu Gui. Umožňují tak říct, jak chtějí flekovat (Flek), licitovat (Ptej se na, Odpovez na nabizeny typ hry, Tak si to jako forhont vezmi), nahlásit hru (Nahlas) a zanést kartu (Zanes).

Obrázek 6.1: Hrac Ostatní jsou již virtuální metody, které slouží k rozhodování ve hře. Do- mácí hráč (tedy uživatelem ovládaný, reprezentovaný třídou Domaci hrac)

51 se na vše zeptá přímo uživatele přes Gui. Síťový hráč (respektive jeho pro- středník) předává své dotazy přes síť, kde se pak také ptá uživatele přes GUI. Počítačem ovládaný hráč využívá metod Priprav se hrat, Priprav se flekovat a Priprav se licitovat k inicializaci jednotlivých objektů, které mají za úkol v dané situaci rozhodnout (Jak nest, Fleky, Licitator), a ke stanovení typu hry, kam až chce licitovat. Uživatelé (domácí i síťoví hráči) je mají prázdné, ovšem dají se na nich zavolat, aby se nemusel při rozhodování odlišovat typ jednotlivých hráčů. Každé rozhodnutí pak zároveň pomocí již zmíněných metod předka oznámí každý hráč přes Jadro (které to předá do všech GUI). Vybrání hry a odhození zařídí metoda Vyber hru a odhod kdyz vylicitovano. Metoda Hraj bere na vstupu aktuální štych (tedy muže tím hráč zjistit, jaké karty smí hrát) a vrátí jej již doplněný o svou vynesenou kartu. Po odehrání každého štychu je to třeba každému říct pomocí Byl zahran stych, toho opět využije jen počítač pro svou inteligenci a ostatní to, stejně jako u přípravných metod, ignorují. Chces licitovat na nám řekne, zda chce tento hráč licitovat na zadaný typ hry. Jestli bude tento hráč flekovat nebo ne se pak můžeme do- zvědět metodami Chces flekovat na hru kdyz jiz fleku v případě, že daný typ hry obsahuje hrovou část a Chces flekovat na sedmu kdyz jiz fleku, pakliže obsahuje sedmovou část, přičemž kolikátý flek již padl potřebuje pro své rozhodnutí jen počítačem ovládaný hráč. Drobnou výjimku ve virtuálních metodách tvoří Predej karty Gui, která neslouží k rozhodování, ale u uži- vatelů předá karty GUI, aby je pak mohlo zobrazit, toto zase pro změnu nezajímá počítačem řízeného hráče.

6.5 Inteligence

6.5.1 Co hrat Co hrat má za úkol vybrat počítačem řízenému hráči, kterou hru hrát a jak odhodit. Je použit po vyhrání licitace a dle pravidel je z ní omezen nejnižší možnou hrou, kterou smí vybrat. Dále také pamatuje na to, že dle pravidel nesmí házet ostré do talonu, pakliže se jedná o hru, kde se hraje o desítky. Pracuje tak, že sestaví seznam všech možných her se všemi možnými odhozy a nechá je pomocí modulu Odhad vysledku ohodnotit, takže u každé takové hry zná svůj zisk nebo ztrátu. Hry s největším ziskem, respektive nejmenší ztrátou, si poznamená. Z nich nechá jen ty s nejlepšími odhozy. A teprve pak náhodně vybere výsledek, který vrátí hráči. Výběr nejlepších odhozů se (v tomto pořadí, dokud lze zúžovat možnosti) snaží pro typ hry ve zkoumaném

52 výběru neodhazovat sedmy, pokud jsou hlášené, neporušovat hlášky, když jde o hru, šetřit trumfy, kde jsou, zbavit se co nejvíce nevhodných karet u betla a durcha a mít po odhozu co nejméně barev. V konstruktoru Co hrat se předají karty hráče, nejnižší možná hra, zda je hráč forhont a nejvyšší povolenou cenu hry. Na tomto objektu pak zavo- láme Vyhodnot, která vrací strukturu Vysledek co hrat, v níž jsou všechny potřebné informace o výběru (hra, včetně barev, ve kterých se hraje, odhoz a odhadovaná cena).

6.5.2 Fleky Fleky je název modulu řešícího rozhodnutí počítačem řízeného hráče, zda a na co (na hrovou či sedmovou část hry) flekovat. Odhad vysledku provede odhad dané hry a na základě toho se stanoví, jak moc se má flekovat. Po- kud typ hry danou část obsahuje (a tedy na ni lze flekovat), jejím odhadem může být prohra (ODHAD PROHRA), kdy pak hráč neflekuje, pravděpo- dobná výhra (ODHAD SPISE VYHRA), kdy se snaží fleknout jednou, nebo téměř určitá výhra (ODHAD VYHRA), kdy se snaží fleknout až čtyřikrát. Posuzování situace je odlišeno pro hráče hrajícího hru (řeší třída Fleky hrac) a protihráčem (řeší Fleky protihrac). Konstruktoru stačí zadat ukazatel na hráče, hranou hru (typ a barvy) a zda je hráč forhont. Fleky hrac a Fleky protihrac mají společného abs- traktního předka Fleky (viz obr. 6.2), od něhož virtuální metodou Zpocti lze získat výsledek ve formě struktury Jak flekovat. Tam jsou zapsány maxi- mální počty fleků, kam má hráč (respektive protihráč) až flekovat, a to jak pro hrové fleky (hra, kilo, betl nebo durch), tak i pro sedmové (sedma nebo dvě sedmy).

6.5.3 Jak nest Jak nest reprezentuje inteligenci počítačem ovládaného hráče při výnosu ka- ret. Hráč si vždy na začátku každé hry vytvoří instanci Jak nest hrac nebo Jak nest protihrac, dle toho, v jaké pozici se nachází (viz obr. 6.3). Tyto dvě třídy mají společného předka Jak nest, jenž poskytuje rozhraní pro ko- munikaci s hráčem a obecně užitečné metody. Jak nest protihrac potřebuje ke svému vzniku znát odkaz na hráče, jemuž říká, co nést, hru, která se hraje (strukturou Hra) a pozici hráče (výčtovým typem Pozice). Naopak Jak nest hrac má pozici jasnou (neboť jeho hráč je ten, co hraje hru), ale

53 Obrázek 6.2: Fleky místo této informace mu řekneme, co dal do talonu. Zatímco hráč použí- vající Jak nest hrac je sám proti ostatním a snaží se uhrát svou hru, tak ten s Jak nest protihrac se mu to snaží překazit a má spoluhráče, na ně- hož musí brát ohled a jemuž může mazat. Jak nest má metodu Co vynest, která z rozehraného štychu na základě všech informací, které během hry Jak nest nasbíral, určí nejlepší výnos z těch hráčových karet, jež dle pra- videl zrovna smí nést (vrací přímo třída Stych, viz kap. 6.3.4). Po každém odehraném štychu je mu navíc třeba (pomocí Byl dohran stych) tento štych předat k prozkoumání, aby mohl z něj získat informace pro další výnosy. Jak nest si pamatuje dvojici instancí Jiny hrac (viz kap. 6.5.4), které zastu- pují jednotlivé ostatní hráče a z rozehraných i odehraných štychů (nevadí dělat opakovaně) jsou schopny postupně vylučovat karty, které již mít nemo- hou a informace z toho plynoucí poskytovat. Všechny nesené štychy si také zapamatuje v zatim neseno . Po získání karet, které se smí nést, se pak s nimi dále pracuje pomocnými metodami pro vybrání těch s nejlepšími vlast- nostmi, to dělá virtuální metoda Vrat nejlepsi vynosy. Je-li nejvhodnějších karet víc, tak se z nich náhodně vybere. Asi nejpoužívanějšími pomocnými metodami třídy Jak nest pro práci se seznamy karet jsou Vrat nejnizsi karty barvy z, která ze zadaného seznamu vrátí nejnižší karty, tedy posloupnost karet, kterou nelze přerušit kartami, jež by mohli mít ostatní (obdobně Vrat nejvyssi karty barvy z nejvyšší). Me- toda Vrat nejvyssi karty ve hre barvy z vrací ze zadaného seznamu nejvyšší

54 Obrázek 6.3: Jak nest karty ve hře, tedy takové, které již nemůže nikdo z ostatních přebít (ob- dobně Vrat nejnizsi karty ve hre barvy z nejnižší ve hře). Pracuje se tak skutečně s co nejvíce možnostmi, ze kterých lze vybrat, což umožňuje více mást uživatele a neposkytovat mu informace o kartách tohoto hráče (na- příklad pokud nepřebije a chce tam hodit co nejnižší kartu, tak lépe vy- brat náhodně z nejnižších karet, jak již bylo popsáno, než vždy nést právě tu jednu nejnižší, čímž soupeř může odvodit, že chybějící ještě nižší má ten druhý a zredukovat počet možností rozmístění karet této barvy). Mimo jiné jsou zde metody pro odstranění karty ze seznamu, pokud je přítomna, (Zkus odstranit kartu z), pro odstranění es a desítek ze seznamu, pokud pří- tomny (Zkus odstranit ostre z) a pro získání všech barev vyskytujících se v daném seznamu karet (Vrat vyskytujici se barvy z). Ale Jak nest také umí o barvě říct, zda už byla nesena, (Barva jeste nenesena), určit, kolikátá do- posud odehraná karta štychu ho zatím zabíjí (Barva jeste nenesena), či zda zatím zabije jeho hráč daný štych (Zabije prozatim tento stych). Pro pře- bitelnost karet zadané barvy tu jsou metody Vrat diry barvy, která vrátí počet děr v barvě pro vše kromě betla, a Vrat diry betla barvy, která dělá to samé pro betla. Protože se hráč i protihráč po rozhodnutí barvy, kterou chce nést chová již (vyjma betla a durcha) stejně, je metoda Jak nest od barvy z, která z daného seznamu povolených karet (po specifikování zda se hraje sedma) obstará výnosy zadané barvy pro všechny hry vyjma betla a dur- cha, v Jak nest, a tedy dostupná oběma. Obdobně při ložených trumfech,

55 kdy chce hráč (respektive protihráč) dohrát co nejlépe, se použije metoda Vrat nejlepsi vynosy hra a sedma trumfy lozene z. U každého zanesení karty je třeba navíc odlišit, kolikátá karta se právě nese a v jaké je kdo pozici. Hráč (resp. protihráč) může při hrách, kde jde o desítky, bez obav zabít štych desítkou jen když ještě za ním nehraje jeho soupeř, pokud tedy od ní nemá eso a onen soupeř už nemůže mít trumfy. Obdobně se každý snaží zabíjet štych (vyjma betla) dostatečně vysokou kartou, když má protivník za ním šanci nemít vyšší. Mazat spoluhráči je třeba také obezřetně, je-li tento protihráč v pozici před hráčem. Při chytání betla se protihráči snaží nést nejnižší hlavně, když hraje hráč ve štychu jako poslední (tedy ho už nemůže být nikdo nucen přebít). Obecně se u Jak nest hrac i Jak nest protihrac získá seznam nejlepších výnosů metodou s názvem Vrat nejlepsi vynosy doplněný o typ hry (jen se neodlišuje hra od kila a, zda se hraje sedma, je odlišeno parametrem, stejně jako kilo u dvou sedem). K tomu používá řadu heuristiky v metodách sloužících například k určení barev, kde jsou nejvíce zranitelné desítky, k určení nejvhodnějších karet k odmazání apod. Soupeř musí také při hrách s trumfy odlišovat, zda nechá chytání hráče na spoluhráčovi, a tedy nést tak, aby hlavně z něj netahal trumfy, nebo bude chytat hráče sám, a pak nebrat na spoluhráče ohled a naopak co nejvíce trumfovat hráče.

6.5.4 Jiny hrac Třída Jiny hrac implementuje imaginárního hráče, používaného modulem Jak nest, s jehož pomocí lze získávat informace z již odehraných karet. K vytvoření je třeba znát hru, která se hraje, a pozici, v níž je hráč, kterého tato instance má zastupovat (výčtovým typem Pozice). Informace si pama- tuje tak, že si drží seznam všech karet, které by ještě mohl mít (muze mit ). Z tohoto seznamu postupně odebírá v průběhu hry za použití znalosti pravi- del. V momentě, kdy má hráč (který tuto instanci Jiny hrac vlastní) nějakou kartu v ruce, dal ji do talonu, či byla nesena, tak je zřejmé, že už ji hráč, jehož instance Jiny hrac zastupuje, mít nemůže, tedy ji z jeho muze mit lze odebrat. K tomu slouží metoda Odstran kartu. Při nedodržení barvy je dle pravidel zřejmé, že tuto barvu hráč (reprezentovaný instancí Jiny hrac) nemá, tedy se mu odeberou z muze mit všechny karty této barvy (meto- dou Odstran barvu). Pakliže hráč není schopen v dané barvě (či trumfech, když již zabito) přebít, lze jej zbavit všech karet vyšších než karta, kterou přebít nemohl (metodou Odstran karty barvy prebijeci hodnoty vyssi nez).

56 Zatímco své karty (případně talon) si odstraní přímo Jiny hrac při vzniku, k odvozování ze štychů slouží metoda Zpracuj stych, která může být vo- lána i víckrát na ten samý štych, a to i v různých stádiích rozehrání (tedy lze zpracovat aktuální rozehraný štych a rozhodnout, jak nést, i na základě informací v tomto štychu a pak po odehrání jej zpracovat znova celý). Celko- věě je pak instance Jiny hrac schopna vyloučit vlastnictví dané karty (me- toda Muze mit kartu), či dané barvy (Muze mit barvu). Dále má metody pro snadnější použití říkající, které barvy již určitě nemá, jaké karty z da- ného seznamu není schopen přebít, kolik nejvýše může mít od jaké barvy či jakou nejvyšší kartu dané barvy ještě může vlastnit apod.

6.5.5 Licitator Licitator slouží počítačem ovládanému hráči k rozhodnutí, kam až má li- citovat (tedy do jakého typu hry dle tab. 5.1 bude při licitaci na případný dotaz odpovídat, že má). K tomu slouží metoda Kam az licitovat, která od- haduje od nejvyšších her, zda ji má hráč šanci vyhrát (metodou Muze hrat). Konstruktoru je pak jen třeba předat odkaz na instanci Pocitac, která lici- tátor vytváří. Tím je zpřístupněn hráč, a tedy i jeho karty. Muze hrat pro zadaný typ hry zavolá metodu s názvem Licitace zakončeným typem hry (vyjma lepších typů, kde stačí jen obyčejná hra s lepší barvou trumfů), které jsou jako parametry předány případné barvy trumfů a pomocných. Při po- suzování, zda je možné danou hru vyhrát se zkoumá, zda je možné splnit podmínky pravidel (viz kap. 5.2) pro výhru. Ve všech hrách, kde se hraje o desítky, se využívá metody Kolik utika, která spočte počet desítek (bez hlášek), které může protihráč až získat. Počítá se, že jakoukoliv desítku či eso hráč nemá, získají ji soupeři, a u trumfové barvy si na každou ještě na- mažou (tedy se počítá dvojnásobně). Výjimkou je, když má hráč od barvy jen eso či žádnou barvu, to pak v dané barvě neuhrají hráči nic. Obdobně při sedmi kartách s esem hráč desítku může vytáhnout esem, a tedy se počítá jako jeho. Tento přístup však neřeší otázku počtu trumfů, to, zda má hráč dostatek trumfů, se již zjistí individuálně dle typu hry (u kila je třeba mít více trumfů než u obyčejné hry). Výsledek odhadu sedmy ovlivní jen počet trumfů a vlastnictví oné sedmy. U kila stačí dle pravidel mít dost desítek. Nakonec u dvou sedem je třeba vlastnit obě sedmy a dostatek pomocných s trumfy. Spojením tohoto se získají odhady pro všechny hry vyjma betla a durcha. Na sto a dvě sedmy se licituje jen za obzvláště dobrých karet, neboť se jedná o extrémně nebezpečný a drahý závazek. Betl se licituje jen

57 pokud má nejvýše jednu díru. Dírou v betlu je rozuměn skok v pořadí ka- ret u barvy, kde má hráč sedmičku, respektive každá karta od barvy, kde sedmičku nemá, samozřejmě, že barva, od které nemá nic, je bez děr. Pro durcha je vyžadováno, aby od každé barvy, kde má hráč přebitelné karty, měl eso a aby počet nejvyšších karet takové barvy byl alespoň takový jako je počet, který mají protihráči (tedy je zaručeno, že z nich hráč vše vytahá, aniž by se dostali ke štychu).

6.5.6 Odhad vysledku Odhad vysledku dopředu odhaduje výsledek hry z karet počítačem ovláda- ného hráče (respektive protihráče), informace, zda je forhont a popřípadě z talonu, má-li jeho znalost k dispozici. Výsledek her odhaduje buď z pozice hrajícího hráče (Odhadni hru), nebo jeho protihráče (Proti odhadni hru), přičemž typ hry (a případně barvu trumfů a pomocných) se těmto meto- dám předá jako parametr. Použit v modulu Fleky (pro hráče i protihráče), ale nejvíce v modulu Co hrat (jen pro hráče). Vzhledem k počtu použití na téže kartách v modulu Co hrat (pro každý možný typ hry se všemi mož- nými barvami) si Odhad vysledku většinu informací o kartách zjistí již při vzniku pomocí metody Prohledni karty, čímž získá o každé barvě její vlast- nosti (uložené ve struktuře Vlastnosti barvy). Toho pak prakticky u každé konkrétní zadané hry využívá metoda Odhadni parametry hra, která naplní stavové proměnné sloužící k rozhodnutí výsledku odhadu. Je-li odhad pro hráče, má k dispozici metody pracující s talonem. Může zjistit, kolik karet má talon od zadané barvy (Kolik karet ma talon barvy), zda obsahuje ta- lon určitou kartu (Ma talon kartu), zda obsahuje kartu s přebíjecí hodnotou hned pod zadanou (Je predesla v talonu), respektive dle přebíjecí hodnoty dvě karty pod ní (Jsou predesle dve v talonu). Odhadni parametry hra za- píše, zda je hra lepší, počty desítek obou stran (včetně hlášek), zda má čtyřicítku, vlastnictví sedmy trumfové, případně pomocné, počet trumfů, respektive pomocných, počet es a barev, zda brání druhé straně ve čtyři- cítce, zda má eso trumfové, respektive pomocné, počty krytých barev pro chytání betla a durcha a počet všech sedem. Z těchto údajů se pak již jen odhad provede, ovšem vyjma betla a durcha v pozici hráče hry, které toho nevyužijí. Odhadni hru, respektive Proti odhadni hru, jen dle typu hry za- volají metodu s názvem Odhadni , respektive Proti odhadni , doplněným o typ hry, ovšem bez lepších typů her, které se zde berou jen jako normální typy s červenou barvou trumfů.

58 Samotný výsledek odhadu je pak předán jako struktura Odhady, která říká, jak moc jistá výhra nebo prohra v jednotlivých částech hry by měla nastat (ODHAD PROHRA pro prohru, ODHAD SPISE VYHRA pro prav- děpodobnou výhru a ODHAD VYHRA pro téměř jistou výhru) a modulem Cenik stanovenou cenu takto dopadnuté hry (v případě prohry se počítá i s flekem proti). Cena v odhadech je použita jen v Co hrat, a tak nevadí, když je upravena pro téměř jisté výhry vynásobením koeficientem ZVY- HODNENI ODHAD VYHRA. Tím se budou hrát spíše jistější hry, ale na druhou stranu se stále může hrát i hra s nižší pravděpodobností výhry, je-li potenciální zisk dostatečně vysoký.

6.6 Jádro

6.6.1 Jadro Jadro je základní třídou aplikace, která se stará o spuštění a propojení všech jeho částí. Při svém vzniku inicializuje knihovny SDL a spouští nové vlákno s grafickým prostředím (reprezentováno instancí třídy Gui, samotné vlákno spuštěné vláknovou funkcí Run Gui). Poté se Jadro aktivuje metodou Run a začne řídit chod aplikace. Při ukončení programu musí Jadro počkat na ukončení vlákna grafického prostředí, na což slouží metoda Pockej na Gui. Při práci s vlákny jsou použity prostředky poskytnuté knihovnou SDL. Ja- dro také zprostředkovává komunikaci mezi hráči a GUI (výjimkou jsou jen požadavky domácího hráče kvůli ovládání), k čemuž využívá již zmíněného postupu v popisu fungování Gui. Tedy nabízí prostředky k oznamování fle- kování, licitaci, nahlášení hry, výnosu karty a zahlášení hlášky hráče, který je identifikován svým indexem v poli hráčů, a to všem GUI, tedy i případ- ným vzdáleným v síťové hře. Dále pak spravuje základní Menu hry, které je vlastně položeným dotazem pro Gui, a na základě odpovědi z GUI od uživatele se pak buď založí nová lokální hra (respektive série her), založí nová série síťových her, vstoupí se do již založené série síťových her, nebo se ukončí aplikace. Po skončení série her se opět program vrací do Menu.

59 6.7 Síť

6.7.1 TCPIP spojeni TCPIP spojeni poskytuje spojení mezi dvěma instancemi aplikace s pou- žitím TCP/IP socketů (TCPsocket), které poskytuje knihovna SDL. Abs- traktní třídě TCPIP spojeni se dá do konstruktoru ID série her, odkaz na Ja- dro a instanci již propojeného TCPsocket. To si zapamatuje jako ID hry , I a socket , načež si socket přidá do struktury SDLNet SocketSet (socket set ), kterou je schopna funkce SDLNet CheckSockets zabezpečit pasivní čekání po zadanou dobu na nově příchozí síťové pakety. Metoda Pockej nez neco prijde tohoto čekání využívá tak, že v cyklu vždy chvíli počká a pak zkontroluje, zda mezitím nedošlo k ukončení, tedy se tak šetří čas procesoru (oproti čistě aktivnímu čekání) a zároveň je čekání přerušitelné, metoda pak vrátí zapl- něný Buffer. Metoda Cekej na odpoved pak ještě navíc u příchozího paketu zkontroluje, že typ odpovídá odpovědi a ID v něm se shoduje s tím ulo- ženým lokálně. Metoda Posli se pak používá pro odeslání Buffer přes síť. Paket se skládá z ID série her, jeho typu (určeno výčtovým typem Prikaz) a dat potřebný pro daný typ paketu. Typ paketu tedy určuje, zda se jedná o odpověď (PRIKAZ ODPOVED) či zda je to jen vzdálené volání metod (ostatní). Tato vzdálená volání mohou být jak pro vzdáleného hráče, tak i pro Jadro (co má zobrazit v GUI). Data jsou uložena jako 32 bitové hodnoty a o jejich zápis a čtení se starají funkce SDLNet Read32 a SDLNet Write32, které jsou nezávislé na platformě (vyřeší problém s endiány). Buffer je třída vytvořená pro snadnější uskladnění dat do pole 32 bito- vých hodnot omezené velikosti (MAX VELIKOST BUFFERU PAKETU ). Buffer nabízí několik přetížených metod Add pro snadné vkládání na ko- nec pole uvnitř a umožňuje i získat počet uložených hodnot. Buffer se dá vytvořit i z již existujícího pole (a jeho velikosti) i prázdný a návratovými metodami Vrat buffer a Vrat velikost lze kdykoliv získat jeho pole a velikost. Potomky TCPIP spojeni jsou TCPIP spojeni hrac a TCPIP spojeni proxy (viz obr. 6.4). Jejich použití je znázorněno na obrázku 6.5. Právě jednu in- stanci TCPIP spojeni hrac vlastní Sitovy hrac a poskytuje metody pro na- pojení do vzdálené hry (Napoj se do hry) či na zpracování dalšího přišlého paketu (Zpracuj dalsi prikaz). Zpracování paketu pouze ověří ID hry a pak dle typu paketu volá obslužnou metodu (na Jadro či na Sitovy hrac) se správně sestavenými parametry. Instanci TCPIP spojeni proxy vlastní Si- tovy hrac proxy a poskytuje metodu pro předání všech jmen hráčů svému

60 Obrázek 6.4: TCPIP Spojeni vzdálenému hráči (Sitovy hrac, s jehož instancí TCPIP spojeni hrac je pro- pojený). Ale také zařizuje vzdálené volání všech metod hráče sloužících k rozhodnutí spolu se všemi metodami Jadro, které mají něco zobrazovat ve všech GUI. Toto vzdálené volání je na TCPIP spojeni proxy vyvoláno za- voláním stejně pojmenované metody jako ta, která se má vzdáleně volat, a v ní pak bude jen sestavení paketu (včetně správného typu a parametrů metody) a jeho odeslání (k TCPIP spojeni hrac).

6.8 Sync

6.8.1 Sync Sync je soubor poskytující nástroje pro synchronizaci činnosti jádra s grafic- kým prostředím (přesně jak popsáno v kap. 3.1). Obsahuje hlavně semafor gui semafor G a proměnnou gui zpracovani zahajeno G použitou jako sig- nál. S nimi pak pracuje funkce Cekej aktivne na, která aktivně počká na za- daný signál. Funke Cekej pasivne po signalu nejdříve využije Cekej aktivne na na zadaný signál, načež vstoupí do zadaného semaforu (signál říkal, že už může), což ji zablokuje (pokud tedy již druhá strana nestihla vykonat vše, co měla a semafor pak nezvedla). Naopak na straně, na kterou se čeká, jsou po- užity funkce Zamkni a dej signal, která zamkne zadaný semafor a hodnotu

61 Obrázek 6.5: Komunikace přes síť proměnné zadané jako signál dá na true, a Odemkni, která jen zapouzdřuje SDL funkci pro odemčení semaforu a ověřuje, že vše proběhlo bez chyb (ji- nak hodí výjimku). Pro ulehčení práce při předání otázky z jádra do GUI slouží funkce Ziskej odpoved gui, která předpokládá již správně vyplněné glo- bální proměnné reprezentující položený dotaz a sama pak pošle grafickému prostředí zprávu o dotazu a pomocí Cekej pasivne po signalu počká na zod- povězení a odpověď pak vrátí (a při tom ještě kontroluje chyby, co mohly nastat).

62 Kapitola 7

Závěr

Pro zprovoznění stačí hru pouze nakopírovat na počítač a případně něko- lik knihoven SDL, pokud ještě na počítači nejsou přítomny. Jednoduché a poměrně přehledné grafické prostředí aplikace umožňuje ovládání myší i klávesnicí, které se zdá být poměrně intuitivní a které se nezasekává a hbitě reaguje. Díky tomu, že vykreslování obrazovky probíhá jen, když je to opravdu potřeba, a tomu, že nejsou použity příliš výpočetně náročné al- goritmy pro počítačem řízené hráče, dosahuje se nízkého vytížení hardware. Vyjma pochopitelných nároků na dostatečné rozlišení (kvůli dostatečné kva- litě obrázků karet), lze hru hrát prakticky kdekoliv, kde běží Windows XP či novější. Inteligence počítačem řízených hráčů se zdá být velmi dobrá, i když ne neomylná, zkrátka srovnatelná s inteligencí normálních lidských hráčů. Samozřejmě, že lze ještě i mnoho vylepšit. Například šikovný grafik by mohl vytvořit stylovější tlačítka, přidat hře logo, které by se zobrazovalo při startu a mohlo by ve zmenšené podobě sloužit i jako ikona. S více kvalitními obrázky karet by pak šel vytvořit i vyšší stupeň rozlišení okna aplikace, popřípadě s jinými, méně detailními obrázky karet (ale zato výstižnými) by šlo rozlišení okna zmenšit. Vyjma grafiky by šla přidat i řada různých nastavení (jako například různé odchylky od pravidel, různé grafické prvky atd.), ovšem muselo by se velmi opatrně, aby se tím nesnížila jednoduchost (a tedy přeneseně i hratelnost) hry. A jako asi u každé hry, kde se vyskytuje simulace lidského uvažování (počítačem řízeného hráče), je na této simulaci prakticky vždy co vylepšovat (nemluvě o skrytých chybách a opomenutích v ní, kterým se při tvorbě dá jen velmi obtížně, pokud vůbec, vyhnout a které se obvykle projeví teprve až po delším užívání aplikace uživateli). Celkově tedy je možné říci, že aplikace splnila všechny kladené poža-

63 davky, a přestože ji lze i (asi jako u většiny jiných programů) v ledasčem vylepšit, je obstojnou implementací počítačové hry licitovaného mariáše.

64 Literatura

[1] C++ Language reference, http://www.research.att.com/ bs/C++.html

[2] Český svaz Mariáše, http://www.marias.cstv.cz/

[3] FalaSoft: Becherovka Mariáš 2.13

[4] Kozmík V.: Renonc, http://marias.aspweb.cz/Default.aspx

[5] Wiki Books: Latex Guide, http://en.wikibooks.org/wiki/LaTeX/

[6] Lazy Foo: SDL Tutorials, http://lazyfoo.net/SDL tutorials/

[7] MSDN Library, http://msdn.microsoft.com/

[8] Pivoňka J.: Re!

[9] SDL domácí stránka, http://www.libsdl.org/

[10] GPWiki: SDL Net Tutorial, http://gpwiki.org/index.php/SDL:Tutorial:Using SDL net

65 Příloha A

Obsah přiloženého CD-ROM

• bc.pdf - tento text v elektronické podobě

• /Sobo Marias Source - projekt ve VS (přeložitelný)

• /Sobo Marias - samotná hra i s potřebnými knihovnami

– Sobo Mrias.exe – SDL.dll – SDL ttf.dll – zlib1.dll – libfreetype-6.dll – SDL net.dll

66