Masarykova univerzita Fakulta informatiky
Automatické vyhodnocování tahů strategických her Bakalářská práce
Ondřej Daněk
Brno, Jaro 2010
Prohlášení Prohlašuji, že tato práce je mým původním autorským dílem, které jsem vypracoval samostatně. Všechny zdroje, prameny a literaturu, které jsem při vypracování používal nebo z nich čerpal, v práci řádně cituji s uvedením úplného odkazu na příslušný zdroj.
Vedoucí práce: RNDr. Vlastislav Dohnal, Ph.D. ii
Poděkování Děkuji zejména vedoucímu mé práce RNDr. Vlastislavu Dohnalovi, Ph.D. za pomoc, připomínky a ochotu při tvorbě práce. Dále pak děkuji mé rodině a blízkým za podporu a pochopení.
iii
Shrnutí Práce se zabývá analýzou, návrhem a implementací vyhodnocovacích algoritmů a automatizačních prvků pro internetovou aplikaci, která je online verzí deskové strategické hry Diplomacie. Obsahem je i popis a podrobná pravidla hry. Dále potom veškeré grafické prvky ve hře.
Klíčová slova strategická hra Diplomacie, vyhodnocovací algoritmus, grafické prvky, php, OOP, mysql, CSS
iv
Obsah 1
Úvod .......................................................................................................................................3
2
Diplomacie ..............................................................................................................................4
3
2.1
Popis hry..........................................................................................................................4
2.2
Pravidla ...........................................................................................................................5
2.3
Fakta o Diplomacii ......................................................................................................... 17
Analýza ................................................................................................................................. 18 3.1
3.1.1
Kaskádové styly ...................................................................................................... 18
3.1.2
Grafické prvky ........................................................................................................ 18
3.2
5
Mapa ............................................................................................................................. 18
3.2.1
Uložení mapy ......................................................................................................... 18
3.2.2
Generování mapy ................................................................................................... 19
3.3
4
Grafická podoba aplikace ............................................................................................... 18
Tahy .............................................................................................................................. 19
3.3.1
Zadávání tahů a dodatečných tahů ......................................................................... 19
3.3.2
Vyhodnocení tahů a dodatečných tahů .................................................................. 19
3.3.3
Doplňování a odebírání jednotek ........................................................................... 19
Návrh .................................................................................................................................... 20 4.1
Diagram datových toků .................................................................................................. 20
4.2
ERD................................................................................................................................ 21
4.2.1
Mapa ..................................................................................................................... 23
4.2.2
Tahy ....................................................................................................................... 23
4.2.3
Zásobovací centra .................................................................................................. 24
Implementace ....................................................................................................................... 25 5.1
Třída Unit ...................................................................................................................... 25
5.2
Mapové funkce .............................................................................................................. 26
5.3
Jednotlivé části hry ........................................................................................................ 27
5.3.1
Zadávání tahů ........................................................................................................ 28 1
6
5.3.2
Vyhodnocení tahů .................................................................................................. 28
5.3.3
Zadávání dodatečných tahů ................................................................................... 29
5.3.4
Vyhodnocení dodatečných tahů ............................................................................. 30
5.3.5
Doplňování a odebírání jednotek ........................................................................... 30
Závěr ..................................................................................................................................... 31
Literatura ..................................................................................................................................... 32 Přílohy ......................................................................................................................................... 33
2
1 Úvod V současné době existuje celá řada internetových „tahových“ her a vzniká stále velké množství nových. Cílem této bakalářské práce není vytvořit další takovou hru, ale převedení poměrně známé společenské hry Diplomacie [1] do on-line podoby. Hru jsme se rozhodli převést proto, že je poměrně populární. Druhým důvodem je časová náročnost hry samotné, která může trvat i několik dní. Posledním důvodem je snaha zpřístupnit hru lidem, kteří ji zatím neznají. Vzhledem k rozsahu se daný úkol (projekt samotný) skládá ze dvou bakalářských prací, z nichž každá řeší předem zadané úkoly. Druhá práce již existuje a je dílem kolegy Bc. Tomáše Novotného *2+. Úkolem mé práce je vytvořit grafickou podobu hry a vyhodnocovací a automatizační algoritmy a herní databáze. Úkolem druhé práce je vytvoření uživatelských databází a jednotlivých funkcí uživatelského rozhraní (registrace, fórum, prostředí pro obsluhu hry). Práce je rozdělena do 6 kapitol. Ve druhé kapitole je podrobněji představena hra Diplomacie a jsou zde uvedena podrobná pravidla. Ve třetí se věnuji analýze projektu, čtvrtá kapitola obsahuje návrh dílčích částí a pátá kapitola se zabývá implementací všech částí. Závěr práce obsahuje hodnocení, nakolik se nám podařilo dosáhnout veškerých cílů. Také jsou zde nastíněny možnosti dalšího rozšíření aplikace v budoucnu.
3
2 Diplomacie 2.1 Popis hry Strategická desková hra Diplomacie v podobě, ve které ji dnes představuje tato práce, byla vytvořena Allanem B. Calhamerem v roce 1954 a vydána komerčně v roce 1959. Hlavním prvkem hry je vyjednáváni, čímž se hra odlišuje od většiny deskových her. Hra navíc potírá téměř naprosto prvek náhody. Celá je založena na principu, kdy každý hráč sám o sobě je natolik slabý, že jedinou jeho nadějí na „přežití“ je vytváření spojenectví s ostatními hráči. Původní verze hry, vytvořená Calhamerem a zde prezentovaná, se hraje na plánu Evropy před 1. Světovou válkou (viz Obr. 1). Ve hře je celkem 7 velmocí (Anglie, Francie, Itálie, Německo, Rakousko-Uhersko, Rusko, Turecko), kde za každou hraje právě jeden ze sedmi hráčů. Každá velmoc – mocnost – ovládá od začátku hry 3 zásobovací centra, kromě Ruska, které vzhledem k velké rozloze ovládá centra 4. Celkem je zásobovacích center 34. Centra, která na začátku hry nepatří žádné z mocností, jsou na území neutrálních států. Pro vítězství ve hře je třeba dostat pod svou kontrolu nadpoloviční většinu center. Hráč musí s ostatními hráči vyjednávat, vytvářet spojenectví, ale i případně umět ve správný čas spojence zradit.
Obr. 1: Hrací plán
4
2.2 Pravidla Pravidla jsou vytvořena kombinací pravidel z několika zdrojů (viz [1], [3]) tak, aby co nejvíce odpovídala reálným skutečnostem. I. Hráči 1) Počet hráčů: 7. 2) Věk hráčů: Diplomacie není vhodná pro děti do 15 let. Původně byla určená dospělým. 3) Rozhodčí: Není potřeba, protože hra funguje plně automaticky. 4) Role hráčů: Při hře zastupuje každý hráč jeden ze států, popořadě Anglii, Francii, Itálii, Německo, RakouskoUhersko, Rusko, Turecko. (viz Obr. 2)
Obr. 2: Mocnosti
II. Potřeby Připojení k internetu a dostatek hráčů k založení hry (partie). III. Vymezení pojmů 1) Mocnost – jeden ze sedmi států, za který hráč hraje. 2) Jednotka – Armáda, nebo flotila. 3) Armáda – vojenská jednotka mocnosti, která se může pohybovat výhradně po souši – teritoriích. (viz Obr. 3)
Obr. 3: Armády
4) Flotila – vojenská jednotka mocnosti, která se může pohybovat výhradně po moři – sektorech a pobřežních teritoriích. (viz Obr. 4)
Obr. 4: Flotily
5) Teritorium – pole na mapě, které leží na souši. 6) Sektor – pole mapy, které je mořem, zátokou či oceánem. 7) Zásobovací centrum – pole na mapě označené černou tečkou (viz. IX). IV. Výchozí situace 1) Přidělování států losem Státy se automaticky rozdělí losem mezi hráče. Pokud nějaký hráč nechce jemu vylosovaný stát, může ho odmítnout. Pokud se tak stane, jsou všechny vrácené státy opět slosovány. Aby 5
došlo k opětovnému losování, musí vrátit stát alespoň dva hráči. Dodatečné losování probíhá maximálně jednou. 2) Rozmístění jednotek Vojenské jednotky má hráč jen na svém vlastním území v těch teritoriích, na kterých jsou zásobovací centra. Rusko s Anglií mají ve hře od počátku po dvou flotilách, ostatní mocnosti po jedné. (viz Obr. 1) V. Cíl hry Získat nad všemi soupeři převahu tím, že dojde k obsazení alespoň 18 z 34 zásobovacích center jednou mocností. VI. Tahy Každý tah představuje půlroční časové období. Ve hře je označujeme jako „jarní tažení“ a „podzimní tažení“. Dva tahy tedy dohromady zahrnují jeden kalendářní rok. Začíná se jarem 1901. Každý tah se skládá ze tří až i pěti částí: diplomacie, zadávání tahů, provádění tahů, případně i zadávání a provedení ústupových tahů a doplňování a odebírání jednotek. 1) Období vyhrazené diplomacii (vyjednávání). Toto období je realizováno vždy mezi dvěma tahy. Hráči se na strategii a podporách mohou domluvit na fórech. Mohou založit vlákno a zakládající hráč může povolit či odepřít přístup kterémukoliv z hráčů. Doporučujeme hráčům, aby si dávali dobrý pozor, jestli nepovolují vstup do vlákna nějakému nepříteli. 2) Přesný návod jak zadávat tahy je popsán v nápovědě. VII. Akce jednotek (armád a flotil) Hráči mohou vydat rozkaz k akci v rámci každého tahu jen těm jednotkám, u kterých to považují za vhodné. Jednotka smí dostat rozkaz maximálně k jediné činnosti. Pozemní armáda bud' k přesunu (který bývá často spojen s útokem na nepřátelskou pozici), nebo k podpoře jiné jednotky (vlastní i cizí), nebo k obraně své pozice. Při podpoře a obraně zůstává jednotka na své pozici. Jestliže se přesunuje, nemůže současně podporovat jinou jednotku v útoku ani obraně. Flotila se může přesunout, bránit dosavadní pozici, podporovat ze svého stanoviště jinou jednotku (pozemní i námořní), nebo provádět transport pozemní armády či invazi. I pro flotily platí, že mohou provádět v jednom tahu maximálně jednu z těchto činností. Jednotka, která nedostane žádný rozkaz, zůstává na své pozici a předpokládáme, že brání své postavení. 1) Prostý přesun 1.1) Každá jednotka se může v jednom tahu přesunout jen do sousedního pole, které má společnou hranici s polem, na kterém se jednotka před tahem nacházela. Armády se samy pohybují jen po pevnině, pomocí flotil i přes moře (viz Obr. 5). Flotily se přesouvají jednak v mořských sektorech, jednak v pobřežních pásmech přímořských teritorií. Jediná výjimka se vztahuje na pozemní armády, které mohou přeplout při transportu nebo invazi v rámci jednoho tahu jeden i víc mořských sektorů (viz pravidlo VII.2.3). Přesunuje-li se flotila z pobřežního pásma pevniny na otevřené moře (z teritoria do sektoru), smí přejít jen do toho 6
mořského sektoru, který má společnou pobřežní hranici s teritoriem, v němž byla před zahájením tahu. Flotila v pobřežních vodách teritoria se může přesunout do pobřežních vod sousedního teritoria jen tehdy, jestliže mají obě teritoria společné mořské pobřeží. Například italská flotila, kotvící v pobřežních vodách teritoria Toskánsko, se smí přesunout do pobřežních vod teritoria Řím. Ale nesmí se z pobřežního teritoria Toskánsko přesunout do pobřežních vod teritoria Benátky, protože obě tato teritoria sice mají společné pevninské hranice, ale nemají společné pobřeží. Flotila, která by chtěla plout z Toskánska do Benátek, by musela obeplout celou Itálii a spotřebovala by na to ve hře 4 tahy (viz Obr. 6).
Obr. 5: Armáda
Obr. 6: Flotila
1.2) Do jednoho teritoria nebo sektoru se může přesunout jen jedna jediná jednotka. Jestliže dostane rozkaz k přesunu do jednoho teritoria nebo sektoru víc jednotek, nebude žádný z těchto rozkazů proveden a všechny jednotky, které se tam měly přesunout, zůstanou na místě (viz Obr. 7). O poli, kam se chtěly přesunout, říkáme, že je zablokované. Pravidlo o zablokování se vztahuje jen na to pole, kam se chtěly přesunout stejně silné jednotky. Jestliže však má některá jednotka převahu nad ostatními, protože ji při přesunu podporují jiné jednotky, potom pro tuto nejsilnější jednotku tento prostor zablokovaný není a může se tam přesunout. Zablokovat teritorium nebo sektor si vzájemně mohou jak jednotky různých mocností, tak jednotky jediného státu.
Obr. 7: Zablokované pole
Dvě jednotky různých států, které dostanou rozkaz, aby si vzájemně vyměnily své pozice, nemohou rozkaz splnit a zůstávají na místě - jsou tedy také zablokované (viz Obr. 8). Na 7
rozdíl od toho dvě jednotky, patřící jediné mocnosti, si svoje pozice vzájemně vyměnit mohou (viz Obr. 9).
Obr. 8: Různé jednotky
Obr. 9: Stejné jednotky
1.3) Přesun, který směřuje na pole, jenž mělo být uvolněno, ale z nějakého důvodu uvolněno nebylo, se také neuskuteční. Příklad: Francouzská armáda dostala rozkaz, aby se přesunula z Burgundska do teritoria Marseille, dosud neobsazeného. Druhá francouzská armáda dostala rozkaz, aby se přesunula z Paříže do Burgundska, které se mělo po odchodu první armády uvolnit. Do Marseille však současně dostala rozkaz k přesunu italská armáda z Piemontu. Italové i Francouzi si vzájemně teritorium Marseille zablokovali, protože jsou stejně silní. Piemontská i burgundská armáda zůstanou na místě. Přesunout se nemůže ani druhá francouzská armáda z Paříže, protože se Burgundsko neuvolnilo. (Viz. Obr 10)
Obr. 10: Blokované pole
1.4) Přesuny v některých zvláštních prostorech 1.4.1) Petrohrad, Španělsko a Bulharsko Tato území se vyznačují dvěma oddělenými pobřežími. Flotily se mohou přesouvat pouze na sousední pobřežní stát bezprostředně sousedící s daným pobřežím, na které se flotila nachází, nebo se může přesunout do moře, které však musí také bezprostředně sousedit s daným pobřežím. Jednotka však ovládá celý stát a stále platí pravidlo VII.1.2. (Viz Obr. 11)
8
Obr. 11: Více pobřeží pro jedno pole
1.4.2) Dánsko a Švédsko Armády i flotily se mohou přesunovat z Dánska do Švédska i ze Švédska do Dánska (Viz Obr. 12). Flotila plující z Baltského moře do Skagerraku se musí nejdřív přesunout do Dánska nebo Švédska (Viz Obr. 13). Totéž platí i když pluje ze Skagerraku do Baltského moře. Dánský prostor zahrnuje nejen pevninu, ale i přilehlé ostrovy a moře mezi nimi. K Dánsku patří i pruh moře až ke švédskému břehu. Společná hranice Dánska a Švédska nerozděluje švédské pobřeží na dvě samostatné části.
Obr. 12: Pohyb armády pře Dánsko
Obr. 13: Pohyb flotily přes Dánsko
1.4.3) Konstantinopol a Bulharsko Armády i flotily se mohou přesunovat z Konstantinopole do Bulharska i z Bulharska do Konstantinopole. Flotila plující z Černého moře do Egejského moře se musí nejdřív přesunout do Konstantinopole. Totéž platí i když pluje z Egejského moře do Černého moře. Konstantinopol zahrnuje nejen pevninu, ale průliv mezi částí asijskou a evropskou. Společná hranice Konstantinopole rozděluje bulharské pobřeží na dvě samostatné části. (Viz Obr. 14)
9
Obr. 14: Pohyb flotily přes Konstantinopol
1.4.4) Kiel Flotily, které vplují do teritoria Kiel ze sektoru Helgolandská zátoka, mohou v dalším kole pokračovat do Baltského moře a naopak. (Viz Obr. 15)
Obr. 15: Pohyb flotily přes Kiel
2) Transport, invaze 2.1) Pozemní armáda se může při tahu přesunout přes moře v těch sektorech, kde jsou její vlastní nebo spojenecké námořní jednotky. Tak třeba ruská armáda se dostane z teritoria Sevastopol do teritoria Ankara (nebo Petrohrad či Bulharsko) pomocí černomořské flotily (viz Obr. 16).
Obr. 16: Přelodění
2.2) Jedna flotila smí převážet jednu armádu.
10
2.3) Každá armáda může být v jediném tahu převezena přes dva i víc mořských sektorů, jestliže jsou tyto sektory ovládány vlastními nebo spojeneckými flotilami (viz Obr. 17). Všechny flotily, kterých se to týká, musí dostat k převozu rozkaz. Každá v něm musí mít uvedeno, že transportuje armádu z teritoria X (výchozí poloha armády před tahem) do teritoria Y (cílová poloha jednotky). Chybí-li třeba jediný z rozkazů, transport se neuskuteční, armáda zůstane na místě. Všimněte si, že při takovém prodlouženém transportu přes několik sektorů zůstávají všechny zúčastněné flotily ve svých sektorech. Jinak by bylo porušeno pravidlo VII, které nedovoluje víc než jeden druh činnosti v jednom tahu - bud' přesun, nebo transport.
Obr. 17: Přelodění přes více sektorů
2.4) Pokud rozkazy k převozu umožňují víc různých cest k cíli, může být armáda transportována po kterékoli z nich. Ovšem jen za předpokladu, že alespoň jedna z těchto možných tras není zablokována tím, že by na flotilu provádějící transport byl veden útok. Jestliže jsou všechny z možných cest takto přeťaty, armáda nemůže být vůbec převezena k cílovému pobřeží a zůstane na místě (své výchozí pozici). 2.5) Při plavbě přes moře jinak platí obecná pravidla o přesunu, jako kdyby se armáda přemisťovala na pevnině. 3) Útok Všechny mocnosti mohou v kterémkoli tahu zaútočit na jednotky kteréhokoli státu a vstoupit na území neutrálních zemí. A to i navzdory všem předcházejícím úmluvám (z dějin je známo mnoho takových příkladů). 3.1) Každá jednotka smí zaútočit na cizí jednotku, která ovládá sousední teritorium nebo mořský sektor. Ke zjištění sil jednotlivých jednotek se sčítá prostý počet jednotek, které se podílejí (podporují jednotku anebo akci přímo provádějí) na útoku nebo obraně. Jestliže nemá útočící ani bránící se jednotka podporu, situace na plánu se nemění (viz Obr. 18). Pokud jedna z jednotek získá početní převahu díky podporám, pak konflikt vyhrává. Jestliže však jsou obě jednotky podporovány stejným počtem jiných jednotek, pak je vítězství na straně útočníků (viz Obr. 19). Jestliže je poražena bránící se jednotka, na kterou byl útok přímo veden, musí ze svého teritoria nebo sektoru ustoupit. Nemůže-li ustoupit, je zajata.
11
Obr. 18: Patová situace
Obr. 19: Ústup obrany
3.2) Pozemní armáda nemůže útočit na flotily v mořských sektorech (viz Obr. 20), protože se na otevřené moře sama v tahu nedostane. Může však napadnout flotilu kotvící v pobřežních vodách (viz Obr. 21), protože ta ovládá celé teritorium, na kterém stojí. A naopak, flotila nemůže vést útok do vnitrozemského teritoria (viz Obr. 22), ale smí zaútočit na armádu nebo flotilu, které ovládají přímořské teritorium (viz Obr. 23).
Obr. 20: Útok armády na moře
Obr. 21: Útok armády na pobřeží
Obr. 22: Útok flotily do vnitrozemí
Obr. 23: Útok flotily na pobřeží
3.3) Při útoku a obraně se berou v úvahu jen ty jednotky, které mají v rozkazu výslovně napsáno, že podporují jednotku Y v útoku na jednotku Z, nebo že podporují jednotku Z při obraně na jejím stanovišti. 3.4) Pozemní armáda může útočit na teritorium, kam ji flotila právě transportuje (invaze). Nesmí však útočit na nepřátelskou flotilu, která je v mořském sektoru.
12
4) Podpora 4.1) Podporu při obraně i útoku mohou poskytnout jen ty jednotky, které stojí v prostoru odděleném jen hraniční linií od prostoru, kam jejich podpora směřuje, a mají tento úkol výslovně uvedený v rozkazu. Jestliže jedna armáda útočí a druhá ji v útoku podporuje, nemusí být obě tyto armády vedle sebe v teritoriích vzájemně spojených společnou hranicí, ale obě tyto jednotky musí přímo sousedit s teritoriem, do kterého útok směřuje. Příklad: první ruská armáda útočí na Rumunsko ze Sevastopolu a v útoku ji podporuje druhá ruská armáda z prostoru Bulharsko. Podpora je platná a účinná, přestože obě ruské armády jsou oddělené rumunským teritoriem. (viz Obr. 24)
Obr. 24: Podpora jednotky
4.2) Zrušení podpory Jestliže je napadena jednotka, která podle rozkazu poskytuje podporu, její podpora se ruší (viz Obr. 25). Musí se teď sama bránit. Právě tak se ruší její podpora, jestliže musí ustoupit ze svého teritoria. V obou těchto případech od ní nedostane podporu ta jednotka, která ji měla podle rozkazu obdržet. Podpora se neruší v případě, že jejím předmětem je útok podporované jednotky na jednotku, která by za normálních okolností útok zrušila. Jestliže německá armáda útočí ze Slezska za podpory rakousko-uherské armády v Haliči na ruskou armádu ve Varšavě a ruská armáda ve Varšavě zároveň útočí na Halič, neruší se podpora rakousko-uherské armády (viz Obr. 26).
Obr. 25: Zrušení podpory
Obr. 26: Útok na podporu ze směru
13
5) Obrana Jednotka, která je napadena, se brání, i když nedostala výslovný rozkaz k obraně. V obraně ji však může podporovat jen ta vlastní nebo spojenecká jednotka, která stojí v sousedním teritoriu nebo sektoru a dostala výslovný rozkaz k podpoře její obrany. Poražená jednotka, která se brání, musí ustoupit nebo je zajata (viz pravidlo VII.3.1) 6) Počet jednotek na poli Na každé poli se může během jednoho tahu nacházet pouze jedna jednotka. Pro toto pravidlo neplatí jakékoliv výjimky a to ani v případě pravidel VII.1.4.1, VII.1.4.2 a VII.1.4.3. (viz Obr. 27)
Obr. 27: Dvě jednotky na jednom poli
7) Ústup Jednotka v boji poražená přesilou nepřátel musí ustoupit do sousedního volného prostoru. Když byly všechny rozkazy provedeny na mapě a přesunuty jednotky, dostanou dodatečný rozkaz k ústupu jednotky v průběhu tohoto tahu poražené. Tyto rozkazy se zadávají stejně jako rozkazy na začátku tahu. Při jejich praktickém provádění platí všechny zásady známé z prostého přesunu jednotek. Jestliže dostane rozkaz k ústupu do stejného volného teritoria nebo sektoru víc jednotek, nesmí tam ustoupit žádná z nich, protože v jednom poli smí být pouze jediná jednotka a při ústupu nelze získat podporu a tedy ani přesilu. Poražená jednotka nesmí ustoupit na pole, ze kterého přichází na její území vítězný útočník. Nesmí ustoupit ani na pole, které bylo v tomto tahu zablokováno, protože se tam chtělo přesunout víc jednotek a žádná přitom nezískala nad ostatními převahu. Nesmí být ani transportována přes moře. Dodatečné rozkazy probíhají maximálně jednou za kolo. 8) Zajetí poražených jednotek Nemá-li poražená jednotka kam ustoupit, protože všechna sousední teritoria jsou buď obsazená, nebo zablokovaná tím, že odtamtud přišel vítězný útočník nebo tím, že by se na ně chtěly přesunout podle rozkazu jiné ustupující jednotky - pak to znamená, že byla poražená jednotka zajatá. Hráč může dát dobrovolně přednost zajetí poražené jednotky před ústupem. 9) Flotila poražená v boji Jestliže je v námořním střetnutí poražena flotila, platí pro ni stejná pravidla jako pro pozemní armádu. Pokud přitom převáží armádu, armáda zůstane ve svém výchozím teritoriu. 14
10)Obležená posádka Když útočí na některé teritorium ze dvou stran více jednotek se stejně silnou podporou, znamená to pro obránce porážku. Útočníci se vzájemně zablokovali, žádný z nich nemůže postoupit na území obsazené obránci, obležená jednotka musí ustoupit, v opačném případě bude zajata. (viz Obr. 28) Pokud je útok veden ze dvou stran a jeden z útočníků má větší podporu než druhý, jsou obránci také poraženi a musí bud' ustoupit (mají-li kam), nebo se jejich jednotka dostane do zajetí. (viz Obr. 29)
Obr. 28: Patová situace – ústup obrany
Obr. 29: Silnější útok - ústup obrany
VIII. Likvidace a doplňování jednotek (armád a flotil) Jak už bylo řečeno, může mít každá mocnost jen tolik jednotek, kolik zásobovacích center ovládá na vlastním i cizím území. To znamená, že ve hře nikdy nemůže být víc než 34 jednotek. Počet armád a flotil se upravuje tak, aby odpovídal počtu ovládaných center, jen po skončení každého jarního tahu - toho tahu, který představuje první polovinu kalendářního roku. Vždycky když tedy skončí „jarní tažení" a hráči provedou všechny akce, porovnáme počet zásobovacích center ovládaných jednotlivými mocnostmi s počtem jednotek, které mají na mapě. Výjimkou je tah první, který se uskuteční na jaře roku 1901, tento rok se jednotky nedoplňují. Tedy první doplňování probíhá až po třetím tahu (jaro 1902). 1) Likvidace přespočetných jednotek Kdo má v této chvíli víc jednotek, než ovládá center, musí počet svých jednotek snížit. Zlikviduje ty armády nebo flotily, pro které se sám rozhodne. 2) Doplňování jednotek Jestliže má hráč na herním plánu méně jednotek, než ovládá zásobovacích center, doplní jejich počet tím, že postaví nové jednotky do volných teritorií na svém vlastním území, kde má zásobovací centra. Jsou-li všechna teritoria se zásobovacími centry na jeho státním území obsazena bud' vlastními, nebo spojeneckými či nepřátelskými jednotkami, nemůže hráč nové jednotky do hry přidat. Musí počkat až na příští jarní tažení. Ale i po dalších dvou tazích zůstanou základní podmínky v platnosti. Proto si hráč musí udržet kontrolu nad vlastními zásobovacími centry, jinak nemá právo postavit nové jednotky. Obsazením cizích zásobovacích center sice znemožňujeme soupeřům vytvářet nové jednotky a získáváme právo na zvýšení 15
počtu vlastních jednotek, ale samo o sobě to neznamená, že můžeme tyto jednotky skutečně nasadit do hry. Ve vnitrozemském teritoriu se zásobovacím centrem lze postavit jen novou armádu. V teritoriu přímořském, kde je zásobovací centrum, je možné vytvořit bud' novou armádu, nebo novou flotilu. Pokud má toto teritorium dvě různá mořská pobřeží (jako například Petrohrad), musí hráč určit, na kterém pobřeží tato flotila kotví. Rozkazy k postavení a umístění nových jednotek zadají hráči po skončeném tahu. IX. Zásobovací centra Na desce je zastupují ta teritoria, která jsou označena černým kolečkem. Každé centrum ovládá mocnost, která má na tomto teritoriu svou jednotku po skončení jarního tažení. V prvním tahu patří každé mocnosti zásobovací centra na jejím vlastním území. V dalších tazích už mohou být obsazena nepřáteli (nebo věrolomnými spojenci). V zásadě platí, že jednotka může opustit teritorium se zásobovacím centrem - ať na vlastním, neutrálním nebo nepřátelském území - na libovolně dlouhou dobu a stále je ovládá, dokud toto teritorium neobsadí jednotka jiné mocnosti při svém úspěšném jarním tažení. Dobytá zásobovací centra zůstávají stále v držení mocnosti, nemůže si na ně dělat nárok mocnost, která toto území nekontrolovala jako poslední. Stát, který ztratí všechna svoje zásobovací centra, může pokračovat v boji, ale nemá právo stavět nové jednotky do té doby, než některé vlastní centrum znovu nezíská. X. Zakončení hry 1) Nezkrácená partie trvá tak dlouho, dokud se jednomu z hráčů nepodaří obsadit nadpoloviční většinu zásobovacích center - 18. Tím si zajistí vítězství, má v Evropě rozhodující moc. To však trvá zpravidla velmi dlouho. 2) Zkrácená partie Hráči se mohou předem dohodnout, že budou ve hře pokračovat po stanovenou dobu a po uplynutí limitu porovnají počty svých jednotek. Zvítězí ten, kdo jich bude mít na mapě nejvíc. I zkrácená hra trvá obvykle nejméně 15 tahů, pří méně tazích se herní děj nemůže pořádně rozvinout. XI. Předčasný odchod ze hry Jestliže některý hráč předčasně odejde, ostatní pokračují v partii a země, kterou odstoupivší hráč zastupoval, se dostala do víru občanské války. Její armády a flotily zůstávají na místě, neútočí, ani se vzájemně nepodporují. A když jsou přinuceny k ústupu, neustupují, ale jsou vzaty do zajetí a odstraněny z desky. Země zachvácená občanskou válkou už nestaví nové jednotky. Přijde-li mocnost zachvácená revolucí o některé zásobovací centrum a musí proto snížit po podzimním tažení počet jednotek, odstraní se z desky vždy ty nejvzdálenější od mateřské země. Vzdálenost se počítá na nutné přesuny nejkratší cestou. Jsou-li dvě nejodlehlejší jednotky stejně vzdáleny a má být likvidována jen jedna, dáváme přednost flotile před armádou.
16
2.3 Fakta o Diplomacii V dnešní době existuje celá řada deskových her nejrůznějších obtížností a spousta těchto her bývá dříve či později převedena do internetové podoby. Diplomacie je však výjimečná tím, jak již bylo řečeno dříve, že téměř úplně potírá prvek náhody. Na internetu již samozřejmě existuje celá škála online Diplomacií, ale doposud se nám nepodařilo najít takovou, která by svými vlastnostmi (jazyk, úroveň služeb uživatelského prostředí, podobnost deskové verze) odpovídala našim požadavkům. To bylo impulzem pro stvoření online verze vlastní. Dnes můžeme najít na internetu mnoho zmínek o hře samotné, například na anglické (viz *4+) a české (viz *5+) wikipedii. Wikipedie také podrobněji pojednává o internetových verzích hry (viz *6+). V zásadě jsou dva typy internetových diplomacií. U prvního typu jsou veškeré prvky a vyhodnocování ve hře prováděny zcela automaticky bez zásahu někoho zvenčí (viz *7+). Druhý typ her se naopak bez takovéhoto zásahu neobejde (viz *3+), hra je takovouto třetí osobou vyhodnocována a tím dochází k časovému i kapacitnímu omezení hry samotné. Samozřejmě dnes existuje celá řada internetových verzí diplomacie včetně Open Source verze. Jelikož ale v budoucnu plánujeme přidat další typy her a další mapy, chtěli jsme vytvořit prostředí hry tak, aby nám bylo blízké a abychom se ve zdrojových kódech a databázích bez problémů orientovali. Proto jsme se rozhodli uskutečnit vlastní projekt na vytvoření české, plně automatické internetové verze hry Diplomacie.
17
3 Analýza Tato práce se zabývá zejména vzhledem a grafickými prvky internetové aplikace kolegy Bc. Tomáše Novotného[2]. Úkolem práce mého kolegy bylo vytvořit uživatelské prostředí pro hráče, jehož součástí je registrace hráčů, vytváření her (včetně přihlašování hráčů a rozlosování států), agenda pro zadávání tahů a kompletní vytvořeni fór (agendy i skriptů). První částí této práce je formátovaní obsahu a vzhledu internetové aplikace*2+ pomocí CSS a také podoba všech grafických prvků. Avšak hlavní a stěžejní částí jsou automatizační prvky hry. Proto druhou částí je uložení mapy do databází tak, aby bylo možné automatizované zpracování. Na to navazuje generování mapy do takové podoby, která odpovídá vždy aktuálnímu resp. danému stavu hry. Další část se zabývá nabídkami při zadávání tahů. Následuje vyhodnocení zadaných tahů a případně zadání a vyhodnocení tahů dodatečných. A poslední je doplňování a odebírání jednotek.
3.1 Grafická podoba aplikace 3.1.1 Kaskádové styly Naší snahou bylo dosáhnout co největší variability a zároveň se držet zaběhlých standardů. Proto jsme se rozhodli veškeré formátování obsahu stránky provádět výhradně pomocí kaskádových stylů (CSS, viz [8]). Hlavní stránku aplikace je třeba rozčlenit na jednotlivé části, aby bylo možné stránku dobře formátovat.
3.1.2 Grafické prvky Jelikož hlavním zobrazovacím médiem ve hře je herní plán, je potřeba věnovat jeho návrhu dostatek času, aby byly jednotlivé prvky na něm zobrazené dostatečně přehledné. Navíc jsme v tomto ohledu omezeni rozlišením obrazovek uživatelů. Z tohoto důvodu jsme se rozhodli optimalizovat celou aplikaci pro rozlišení 1024x768. Proto je potřeba vytvořit přehledný herní plán a reprezentanty armád a flotil.
3.2 Mapa 3.2.1 Uložení mapy Jedním ze stěžejních prvků je uložení mapy do herních databází takovým způsobem, aby bylo umožněno další automatizované zpracování. Nejjednodušší by v tomto případě bylo, kdyby měl herní plán podobu pravidelné (např. čtvercové) sítě. V případě že tuto podobu nemá, je třeba jej převést na graf a do databází zaznamenat vrcholy a hrany tohoto grafu. Náš případ je ale o to těžší, že herní plán obsahuje pole s více pobřežími.
18
3.2.2 Generování mapy Podstatnou částí je také automatické generování mapy (herního plánu) tak, aby odpovídala dané skutečnosti. Hra musí umět zobrazit jednotky na jejich pozicích pro hru a aktuální období. Také musí umět zobrazit jakékoliv období z historie.
3.3 Tahy 3.3.1 Zadávání tahů a dodatečných tahů Vytvořit agendu pro zadávání tahů bylo předmětem práce kolegy Novotného *2+. Mým úkolem vytvořit funkce, které pro agendu dodají potřebná data. Na jejich základě je potom hráč schopen zadat tahy pro svoje jednotky. To stejné se týká i dodatečných tahů.
3.3.2 Vyhodnocení tahů a dodatečných tahů Stěžejní částí práce je vyhodnotit na základě zadaných dat pohyby jednotlivých jednotek po herním plánu. Hra nabízí několik různých druhů akcí (obrana, útok, podpora a přelodění), se kterými se musí umět algoritmus vypořádat. Důležité je, aby vyhodnocení jednotlivých akcí proběhlo ve správném pořadí.
3.3.3 Doplňování a odebírání jednotek Pro doplňování a odebírání jednotek bylo nutné dobře ošetřit ukládání a následné zpracování dat o jednotlivých zásobovacích centrech. Opět však bylo cílem vytvořit pouze vhodné funkce, nikoli agendu samotnou.
19
4 Návrh V této kapitole se podrobněji zabývám požadavky na jednotlivé části mé práce. Hlavním tématem je návrh databáze pro celou. Podrobněji se zde rozepisuji o mapě, tazích a zásobovacích centrech, neboť právě tyto tři témata jsou z velké části závislá na správném návrhu celé databáze. Různé možnosti uložení dat pro hru jsem poměrně dlouho analyzoval a zvažoval všechny klady a zápory jednotlivých možností. Podrobněji se o jednotlivých konkrétních problémech rozepisuji v následujících podkapitolách.
4.1 Diagram datových toků Diagramy datových toků jsou v nezměněné podobě převzaty od kolegy Novotného*2+ za účelem nastínění fungování celé aplikace. Konkrétně systémový diagram datových toků (viz Diagram 1) a dva diagramy datových toků první úrovně (viz Diagram 2 a 3).
Diagram 1: Systémový diagram datových toků
20
Diagram 2: Diagram datových toků 1. úrovně – Administrativa
Diagram 3: Diagram datových toků 1. úrovně – Hra
4.2 ERD Podle požadavků z diagramu datových toků jsme vytvořili datovou strukturu celého projektu – ERD (viz Diagram 4). Entitními množinami Users, User_permissions, Configurations, Games, 21
Countries, Forum_categories, Forum_threads a Forum_messages a Thread_permissions se ve své práci podrobněji zabýval kolega Novotný *2+. Předmětem mé části práce jsou entitní množiny Map, Army_map, Navy_map, Map_units_position, Map_fields_specification, Supply_centres, Engaged_supply_centres, Rounds, Units, Units_details a Forbidden_fields.
Diagram 4: ERD
22
4.2.1 Mapa Mapa je jednou ze stěžejních částí celého projektu. Jednou z možností by bylo vyřešit celou mapu čistě pomocí programu (skriptu a několika funkcí). Cílem této práce ale bylo vytvořit programové prostředí, odpovídající pravidlům hry Diplomacie (viz 2.1), pro libovolnou mapu. Úkolem tedy bylo navrhnout databáze tak, aby bylo možné do nich uložit jakoukoliv mapu, která by mohla vzniknout. Jak již bylo popsáno výše (viz 3.3.1), hlavním problémem mapy je existence více pobřeží pro jedno pole. Tato pole jsou na klasickém plánu pouze 3 a tak by bylo nasnadě právě programové řešení v podobě jednoduchých výjimek. A však tímto řešením by nebyla naše snaha naplněna. Problém více pobřeží pro jedno pole tkví v tom, že se pole chová různými způsoby za různých okolností. Je tedy třeba na takovéto pole nahlížet jako na několik různých polí avšak za splnění podmínky, že se jedná stále o pole jedno a tedy že na něm může být v daném okamžiku hry jen jedna jednotka. Na základě zvážení všech možností jsem se nakonec rozhodl pro použití dvojího číslování jedné mapy resp. herního plánu (viz přílohy *Obr. A+ a *Obr. B+). Každé pole tak má přidělena dvě čísla, z nichž jedno je zcela unikátní. Na základě všech těchto podmínek byla vytvořena datová struktura samotné databáze. Stěžejní pro mapu je entitní množina Map, ve které jsou uchovávána všechna pole s jejich názvy a základní specifikací. Na ni jsou navázány entitní množiny Map_units_position (sloužící k vykreslení jednotek na hracím plánu), Map_fields_specification (uchovávající detaily speciálních polí) a Army_map a Navy_map (asociativní seznamy hranic pro oba typy jednotek).
4.2.2 Tahy Druhou neméně důležitou částí je umožnění hráčům provádět akce (tahy) se svými jednotkami. Nejde pouze o vyhodnocování tahů. Součástí této části je podat hráči nabídky jednotlivých tahů, které může provádět se svými jednotkami. V tomto ohledu existují dva náhledy na věc. První pohled je takový, že hra nabídne hráči naprostou volnost, co do možností tahu. Hráč si tedy může v takovémto případě volit i tahy, které ve skutečnosti nejsou možné. Je potom na kontrolních mechanizmech hry, aby tyto tahy vyřadila (zrušila). Druhý pohled a také směr, kterým jsem se s řešením ubíral, je nabídnout hráči jen ty tahy, které jsou pro postavení jeho jednotek skutečně proveditelné (vždy je tu však faktor věrolomných spojenců, kteří nedodrží dohody). Z tohoto důvodu tedy již není nutné kontrolovat proveditelnost jednotlivých tahů z hlediska mapy, ale zůstává zde nutnost zkontrolovat konzistenci jednotlivých příkazů. Aby bylo možné jednotlivé tahy s jednotkami provádět, je potřeba i existence jednotek samotných. Pro tyto účely byla vytvořena entitní množina Units (uchovávající základní údaje o každé jednotce, která se kdy ve hře objevila). Ta je navázána na entitní množinu Countries*2+(pro určení příslušnosti dané jednotky), Units_details (k uchování detailů dané jednotky pro jednotlivá kola) a Forbidden_fields (uchovávající zablokovaná a obsazená pole pro dané kolo dané hry, případně i danou jednotku). Units_details resp. Forbidden_fields je navázána na Map (viz 4.2.1) pro určení konkrétní polohy jednotky resp. zablokovaného pole, druhá jmenovaná je pak navázána ještě na 23
Games[2], pro určení příslušnosti pole k dané hře a období. Poslední entitní množina tahů je Rounds, která je navázána na Games a uchovává časové údaje o jednotlivých kolech dané hry.
4.2.3 Zásobovací centra Poslední důležitou součástí je agenda zásobovacích center. Ta jsou vlastně stěžejní částí celé hry, neboť právě na základě nich lze určit úspěšnost jednotlivých hráčů. Z důvodu dalšího zpracování (např. statistiky hry) je nutné uchovávat i informaci o obsazení jednotlivých zásobovacích center ve hře pro dané kolo. Nestačí tedy pouze uchovat údaje o tom, které centrum má pro danou hru který hráč v držení. Pro tyto účely slouží entitní množiny. První z nich je Supply_centres (jsou v ní uloženy informace o všech zásobovacích centrech na herním plánu) která je navázána na množinu Map a také na druhou entitní množinu Engaged_supply_centres (která uchovává informace o obsazení daného zásobovacího centra danou zemí pro danou hru), jenž je dále navázána na Countries a Games.
24
5 Implementace Na základě dobrých zkušeností, umístění celé aplikace (internet) a použitých prostředků kolegou Novotným jsem se rozhodl pro použití skriptovacího jazyka PHP verze 5 (viz *9+ a *10+), jenž plně podporuje objektově orientované programování, které mi podstatně zjednodušilo jinak téměř neřešitelné úkoly. Navíc tento jazyk umožňuje poměrně dobré generování grafiky (obrázků), které ve své práci používám ke generování herního plánu. K uchování dat byl zvolen databázový systém MySQL verze 5 (viz [11] a [12]). K základní úpravě vzhledu aplikace bylo využito CSS (viz [8] a [13]).
5.1 Třída Unit V této kapitole podrobně popíši třídu Unit, která je klíčovou třídou pro moji část práce. Třída reprezentuje libovolnou jednotku ve hře. Atributy: id – identifikační číslo jednotky country_id – příslušnost k dané zemi state – stav, ve kterém se jednotka nachází period – období, ve kterém se jednotka právě nachází position – pozice (field_id) jednotky na hracím plánu position_p – pozice (position) jednotky na hracím plánu position_type – typ pole na kterém se jednotka nachází action – akce jednotky attack_type – typ útoku jednotky destination – cílová pozice (field_id) jednotky destination_p – cílová pozice (position) jednotky destination_type – typ cílové pozice support_unit – pozice podporované jednotky support_unit_id – identifikační číslo podporované jednotky suplementary_destination – náhradní cílová pozice strength – síla jednotky strength_before – maximální síla jednotky unit_type – typ jednotky retreat – příznak zda jednotka ustupuje alive – příznak zda je jednotka naživu move – příznak zda se jednotka posune
25
Metody a funkce: getInfo($id, $period) – aktualizuje hodnoty atributů třídy z databáze. Parametr id identifikuje
konkrétní jednotku a parametr period určuje, za které období se mají hodnoty načíst. getMoveInfo() – aktualizuje hodnoty atributů, které se týkají akce, pro danou jednotku. getUnits($period, $condition) – na základě podmínky condition vrací seznam jednotek pro dané období (period). getNeighbours($game_id) – vrací všechna pole, na která může jednotka podniknout útok (i přeloděním). getNeighbourUnits($game_id) – vrací jednotky, které mohou být danou jednotkou podporovány, nebo přeloďovány. setMove($action, $destination, $support_unit) – zapisuje běžný tah pro danou jednotku. Ukládá do databáze parametry action, destination a support_unit. setMove($s_destination) – zapisuje dodatečný tah pro danou jednotku. Ukládá do databáze parametr s_destination. deleteMove($unit_id, $period) – maže běžný tah pro danou jednotku. deleteUnit($unit_id) – smaže danou jednotku (v databázi nastaví state na 0). createUnit($country, $type, $position, $period) – vytvoří jednotku na základě vstupních parametrů. Jednotku uloží do databáze. setCommonTurn($units, $ob, $game_id) – zapíše výsledky běžného tahu pro všechny jednotky ze vstupního parametru units. Zároveň zapíše do databáze seznam blokovaných polí ze vstupního parametru ob. setSupplementaryTurn ($units, $game_id) – zapíše výsledky dodatečné tahu pro všechny jednotky ze vstupního parametru units.
5.2 Mapové funkce Tento skript obsahuje všechny funkce, které slouží pro výběr jednotek a jejich nabídky při zadávání tahů, dále pak vyhodnocování tahů a veškeré nabídky vyžadující kombinovat mapu s jednotkami. Zde následuje popis jednotlivých funkcí: getFieldName ($field) – vrací název území na mapě na základě parametru field. sortFieldsByName ($fields) – vrátí seznam setříděných polí podle jména. uniqueFields ($fields, $fields2=array(), $field=NULL) – seřadí vstupní pole fields a vymaže položky s hodnotou NULL, zároveň zajistí unikátnost každé hodnoty. Jestliže je zadán i parametr pole fields2, pak jej spojí se vstupním polem fields a provede kroky viz výše. Pokud je zadán i parametr field, pak zkontroluje, jestli upravený parametr pole neobsahuje a pokud ano, pak pole ze seznamu smaže. Vrací upravené seznam polí. getNeighbourFields($field, $type, $unit_type=NULL) – vrátí všechna sousední pole pro vstupní parametr field. Na základě parametru type umožňuje vyhledávání podle typu pole
26
v odpovídající mapě. Podle parametru unit_type pak vyhledává v mapě odpovídající typu jednotky. getNeightbourFieldsForSupport ($field, $unit_type) – vrátí pole, pro která může být z daného pole definovaného vstupním parametrem field nabídnuta podpora. Na základě parametru unit_type je zvolena mapa odpovídající typu jednotky. findShips ($game_id, $field) – nalezne lodě pro danou hru (game_id) v okolí pole zadaného parametrem field. findLands ($field) – vrátí sousední pobřeží pro pole zadané parametrem field. getSpecialFields ($field, $all = 0) – vrátí speciální pozice, které jsou variantami parametru field, jestliže je parametr all nastaven na 0, pak vrací opačné typ pozicí, pokud je all 1, pak vrací všechny pozice včetně hodnoty field. changeSpecialFields ($fields, $change) – vrátí zpět parametr fields, kde speciální pole budou nahrazena, nebo rozšířena o jejich ekvivalenty v závislosti na parametru change (0, 1). crossOfferFields ($game_id, $from) – vrátí nabídku polí pro danou hru (game_id), na která se lze ze vstupního pole (field) přeloděním dostat. getFieldsWithUnits ($game_id, $fields, $type=NULL, $field=NULL) – vrátí pole ze vstupního parametru fields pro danou hru (game_id), na kterých se nachází jednotky. Jestliže je zadán i parametr type respektive field, pak vrací jen pole s jednotkami daného typu, respektive stejného typu jako má pole field. crossControl ($u_pos, $units) – zjistí, zda je přelodění možné pro jednotku definovanou parametrem u_pos v seznamu jednotek z parametru units. Vrátí TRUE resp. FALSE pokud je přelodění možné resp. možné není. attackControl ($game_id, $from, $to, $unit_type) – na základě vstupních parametrů zjistí, zda je útok, respektive útok přeloděním, možný pro danou hru (game_id). getSupplemetaryNeighbourFields ($position, $unit_id, $unit_type, $game_id, $period) – vrátí seznam polí, na která může jednotka zadaná parametrem unit_id provést
dodatečný tah (jsou vyloučena blokovaná pole na základě parametru game_id a period). countSupplyCentres ($game_id, $country) – vrací počet zásobovacích center pro zemi zadanou parametrem country v dané hře (game_id). setEngagedSupplyCentres ($game_id, $period) – zapíše do databáze všechna obsazená zásobovací centra v daném kole.
5.3 Jednotlivé části hry V této podkapitole se budu podrobněji věnovat jednotlivým funkčním celkům mé práce. Konkrétně zadávání tahů, vyhodnocování tahů, zadávání dodatečných tahů, vyhodnocování dodatečných tahů a doplňování a odebíraní jednotek.
27
5.3.1 Zadávání tahů Jak již bylo popsáno v kapitole 4.2.2, rozhodl jsem se nabízet hráči jen ty možnosti, které jsou na herním plánu pro dané rozmístění jednotek skutečně možné. Proto hráč vždy dostává seznam jen takových polí, na která se může v daném tahu přesunout. Toto je zajišťováno pomocí volání funkcí getNeighbours a getNeighbourUnits třídy Unit. Tyto funkce potom využívají skriptu mapových funkcí, na základě kterých vrací aplikaci potřebná data. Tím je zajištěno maximální hráčské pohodlí.
5.3.2 Vyhodnocení tahů Vyhodnocování tahů je prakticky centrálním mozkem aplikace. Je to vlastně to, kvůli čemu jsme se do celého projektu pouštěli. Naprogramování vlastní verze výpočetního algoritmu nám dává dostatečnou míru flexibility i do budoucna pro další rozšíření hry. K tomu přispívá i dokonalá znalost kódu. Skript pro vyhodnocování tahů funguje na základě postupného vyhodnocování jednotlivých herních situací. Skript si na počátku načte do seznamu units všechny jednotky, se kterými bude nadále operovat. Vybírá si ty jednotky, které jsou pro danou hru a dané období stále ve hře a mají zadaný tah (jednotka má nastavenou proměnnou state na hodnotu 2). Po načtení jednotek pokračuje skript kontrolou konzistence akcí zadaných jednotlivým jednotkám. Začíná proveditelností přelodění, tedy zda mají všechny flotily potřebné k přelodění armády nastavenou správnou akci a dále zda mají nastavený správný start (výchozí pozici armády) i cíl (konečná destinace armády). Dále kontroluje příkazy podpor, konkrétně zda se příkazy podporujících jednotek shodují s příkazy podporovaných jednotek. V další části jsou nejprve přičteny síly z jednotlivých podpor a poté jsou podpory a přelodění rušeny na základě pravidel pro hru platících. V případě že je některá podpora zrušena, pak je síla opět odečtena. Dále jsou opět prověřována přelodění a případně rušeny podpory, na které přeloďovaná jednotka útočí. Skript se dále dostává do závěrečné fáze – vyhodnocování jednotlivých útoků. Nejprve jsou jednotky seřazeny podle síly, aby bylo postupováno od jednotek nejsilnějších. Poslední část skriptu vyhodnocuje útoky. Z důvodu proveditelnosti byly všechny možné případy rozebrány na elementární situace a ty jsou ve skriptu následně vyhodnocovány. Tyto situace jsou celkem 4. První z nich je útok na bránící se jednotku (A útočí na B a B se brání). Je zde potřeba vyhodnotit, zda se neútočí na jednotku vlastní. Potom se zkontroluje, jaký je poměr sil bránící se a útočící jednotky. Jestliže útočící jednotka prohraje, pak se již žádné její další kolize nevyhodnocují. Pokud však vyhraje, je bránící se jednotce nařízen ústup. Druhým případem je útok dvou jednotek na stejné území (A útočí na B a zároveň C útočí na B). Opět je vyhodnocen poměr sil obou jednotek. U tohoto případu je třeba ještě prověřit, zda si protivníkova jednotka nevyměňuje pozici s jednotkou jinou (A útočí na B a zároveň B útočí na A). Pokud by si pozici vyměňovala, je nutné ještě zohlednit, zda se jedná o jednotky téhož, nebo dvou 28
různých států. Pokud by se jednalo o jednotky dvou různých států, výměna by nebyla možná a opět by bylo potřeba vyhodnotit síly obou protivníků. Třetí situace se týká právě zmíněné záměny pozic dvou jednotek. Jestliže se jedná o jednotky dvou různých států, je tato kolize vyhodnocena na základě sil obou jednotek. Pokud se však jedná o jednotky stejného státu, pak nemůžeme až do konce vyhodnocování tah povolit, neboť může dojít k jiné kolizi. Proto jsou obě jednotky přidány na seznam kolizí. A poslední případ prověřuje útok na pole, na kterém se nachází jednotka, která však útočí na pole jiné (A útočí na B a B útočí na C, kde C je pole). Zde je třeba opět vyhodnotit, zda se nejedná o dvě jednotky stejného státu (protože jednotka nemůže přinutit k ústupu druhou jednotku stejného státu), a dále sílu útočící jednotky. Jestliže má sílu větší než 1, pak je útok proveden, v opačném případě a v případě dvou jednotek stejného státu je případ opět zapsán na seznam kolizí. Poté, co jsou prověřeny všechny tyto případy, porovnáním vždy všech jednotek navzájem, jsou jednotkám nastaveny příznaky určující další osud každé z nich. Jsou to proměnné move a retreat třídy Unit. Proměnná move nabývá hodnoty 1, 0 nebo -1. Hodnota 1 signalizuje, že jednotka může být přesunuta. Hodnota 0 oznamuje, že jednotka čeká na další vyhodnocení anebo nebyla vůbec vyhodnocována (neútočila). A -1 znamená pro jednotku to, že útok se nepovedl a jednotka tak zůstává na místě. Proměnná retreat nabývá hodnot pouze dvou a to 0 a 1, kde 0 znamená pro jednotku, že může zůstat na aktuální pozici a 1 signalizuje nutnost ústupu jednotky. Poslední část skriptu vyhodnocuje kolizní situace. Jedná se zejména o dva případy a to posun několika jednotek v řadě (A útočí na B, B útočí na C, C útočí na D, atd.) a obdobně posun několika jednotek v kolečku (A útočí na B, B útočí na C a C útočí na A). K těmto kolizím však dochází pouze pokud dvě jednotky za sebou jsou obě ze stejného státu nebo pokud útočník má sílu 1. Prochází se seznam kolizí a zjišťuje se, zda jaké nastavení mají jednotky, na jejichž vyhodnocení se čeká (tímto způsobem je vyřešen první případ). Pokud kontrolní podmínka zjistí, že nebyla žádna kolize v daném průchodu vyhodnocena (vede na druhý případ – případ kolečka), pak je zkontrolováno, jestli nějaká z jednotek účastnících se kolize nemusí ustoupit. Pokud ano, zůstávají všechny jednotky daného kolečka na místě. Jestliže ne, všechny jednotky se posunou. Poté, co jsou vyhodnoceny i tyto kolizní situace, je vše vyřešeno a na seznam units je zavolána funkce setCommonTurn ze třídy Unit. Ta již zapíše veškeré pohyby i potřeby dodatečných tahů do databáze.
5.3.3 Zadávání dodatečných tahů Úkolem této části, podobně jako při zadávání běžných tahů, je nabídnout hráči seznam polí, na která může jeho jednotka ustoupit. Tento seznam je získán pomocí funkce getNeighbours třídy Unit. Hráč dostává seznam sousedních polí bez polí, která jsou blokována.
29
5.3.4 Vyhodnocení dodatečných tahů Tento skript pouze nalezne kolize mezi ustupujícími jednotkami. Jestliže kolize existuje, pak jednotky účastnící se této kolize zruší (nastaví state na 0). Jednotky, které ústup zvládly bez kolize, přesune na jejich nové pozice a vše opět zapíše do databáze pomocí funkce setSupplementaryTurn třídy Unit.
5.3.5 Doplňování a odebírání jednotek Pro doplňování a odebírání jednotek byly vytvořeny metody deleteUnit a createUnit ve třídě Unit. K tomu aby mohlo být vyhodnoceno, kolik má země zásobovacích center, slouží mapová funkce countSupplyCentres.
30
6 Závěr Tato práce obsahuje pravidla doplněná obrázky a popis hry Diplomacie. Dále obsahuje analýzu problematiky a návrh jejího řešení včetně návrhu databází. Závěrečná část popisuje některé části implementace výpočetních algoritmů a herních skriptů. Vše je možné vyzkoušet díky funkční internetové aplikaci kolegy Novotného (viz *2+) na internetové adrese http://diplomacie.tym.cz. Zde jsou implementovány všechny popsané algoritmy. Bohužel zde však není možné vyzkoušet funkčnost zadávání dodatečných tahů, vyhodnocování dodatečných tahů a přidávání a odebírání jednotek, jelikož herní agenda pro tyto funkce nebyla předmětem mé práce. Předpokládám však, že tyto chybějící části budou v nejbližší době doplněny. V současné chvíli je celá hra po spojení obou prací téměř hotova, proto si troufám říct, že se nám podařilo vytyčených cílů dosáhnout. Navíc některé části hry jsou již připraveny na rozšíření, která do budoucna plánujeme. Mezi hlavní plány patří rozšíření aplikace o nové typy her (například v počtu hráčů) a doplnění nových herních plánů. Dále chceme nabídnout hráčům více interaktivity v podobě většího množství uživatelských nastavení. V neposlední řadě plánujeme i doplnění funkce herních statistik. Do budoucna tedy máme v plánu se projektu i nadále věnovat. Vytvořená práce splňuje zadání bakalářské práce.
31
Literatura *1+ Zapletal, Miloš: Velká kniha deskových her. Praha, Mladá fronta, 1991, s. 105 – 112 [2] Bc. Tomáš Novotný, Internetová aplikace pro strategické hry *bakalářská práce+, Fakulta Informatiky Masarykovy univerzity, 2010 [3] Diplomacie – DiploNET v1.2 [Online], http://www.diplomacie.net/ (leden 2010) [4] Diplomacy (Game) – Wikipedia, the free encyclopedia [Online], http://en.wikipedia.org/wiki/Diplomacy_(game) (březen 2010) [5] Diplomacie (hra) – Wikipedie, otevřená encyklopedie [Online], http://cs.wikipedia.org/wiki/Diplomacie_(hra) (květen 2010) [6] Internet Diplomacy – Wikipedia, the free encyclopedia [Online], http://en.wikipedia.org/wiki/Internet_Diplomacy (březen 2010) [7] Play Diplomacy Online [Online], http://playdiplomacy.com/ (duben 2010) [8] Staníček, Petr. CSS Kaskádové styly: kompletní průvodce. Vyd. 1. Praha: Computer Press, 2003, 178 s. ISBN 80-7226-872-4 [9] PHP: PHP – Manual [Online], http://www.php.net/manual/en/ (únor 2010) [10] Tansley, David. PHP a MySQL :vytváříme dynamické webové stránky. Praha: Softpress, 2002, 480 s, ISBN 80-86497-40-2 [11] MySQL :: MySQL 5.0 Reference Manual [Online], http://dev.mysql.com/doc/refman/5.0/en/ (leden 2010) [12] DuBois, Paul. MySQL profesionálně: komplexní průvodce použitím, programováním a správou MySQL. Vyd. 1. Praha: Mobil media, 2003, 1071 s, ISBN 80-86593-41-X [13+ Jak psát web, návod na html stránky *Online+, http://www.jakpsatweb.cz (březen 2010)
32
Přílohy Příloha Obr. A: Číslování polí
33
Příloha Obr. B: Číslování polí včetně pobřeží
34
Příloha C: Definice tabulek databází pro MySQL (celý projekt) -- Struktura tabulky `army_map` CREATE TABLE `army_map` ( `field1` int(11) NOT NULL, `field2` int(11) NOT NULL, PRIMARY KEY (`field1`,`field2`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; -- Struktura tabulky `configurations` CREATE TABLE `configurations` ( `user_id` int(11) NOT NULL, `forum_sort` tinyint(4) NOT NULL default '1', `messages_on_page` tinyint(4) NOT NULL default '25', `mailing` tinyint(1) NOT NULL default '0', PRIMARY KEY (`user_id`) ) -- Struktura tabulky `countries` CREATE TABLE `countries` ( `country_id` int(11) NOT NULL auto_increment, `game_id` int(11) NOT NULL, `user_id` int(11) NOT NULL, `power` int(2) default NULL, `state` int(2) NOT NULL default '0', PRIMARY KEY (`country_id`) ) -- Struktura tabulky `engaged_supply_centres` CREATE TABLE `engaged_supply_centres` ( `game_id` int(11) NOT NULL, `position` int(11) NOT NULL, `country` int(11) NOT NULL, `period` int(11) NOT NULL ) -- Struktura tabulky `forbidden_fields` CREATE TABLE `forbidden_fields` ( `game_id` int(11) NOT NULL, `field_id` int(11) NOT NULL,
35
`position` int(11) NOT NULL, `unit_id` int(11) NOT NULL, `period` int(11) NOT NULL ) -- Struktura tabulky `forum_categories` CREATE TABLE `forum_categories` ( `category_id` int(11) NOT NULL auto_increment, `name` varchar(30) collate utf8_unicode_ci NOT NULL, `description` varchar(100) collate utf8_unicode_ci NOT NULL, `type` tinyint(4) NOT NULL, PRIMARY KEY (`category_id`) ) -- Struktura tabulky `forum_messages` CREATE TABLE `forum_messages` ( `message_id` int(11) NOT NULL auto_increment, `thread_id` int(11) NOT NULL, `author` int(11) NOT NULL, `title` varchar(30) collate utf8_unicode_ci NOT NULL, `text` text collate utf8_unicode_ci NOT NULL, `date` timestamp NOT NULL default CURRENT_TIMESTAMP, `reply_to` int(11) default NULL, PRIMARY KEY (`message_id`) ) -- Struktura tabulky `forum_threads` CREATE TABLE `forum_threads` ( `thread_id` int(11) NOT NULL auto_increment, `category_id` int(11) NOT NULL, `game_id` int(11) NOT NULL default '0', `name` varchar(30) collate utf8_unicode_ci NOT NULL, `description` varchar(100) collate utf8_unicode_ci NOT NULL, PRIMARY KEY (`thread_id`) ) -- Struktura tabulky `games` CREATE TABLE `games` ( `game_id` int(11) NOT NULL auto_increment, `name` varchar(50) collate utf8_unicode_ci NOT NULL, `description` varchar(200) collate utf8_unicode_ci NOT NULL, `period` int(11) NOT NULL default '1',
36
`state` int(2) NOT NULL default '0', `type` int(2) NOT NULL default '1', `map` int(2) NOT NULL default '1', `password` varchar(32) collate utf8_unicode_ci default NULL, PRIMARY KEY (`game_id`) ) -- Struktura tabulky `map` CREATE TABLE `map` ( `field_id` int(11) NOT NULL auto_increment, `position` int(11) NOT NULL, `field_specification` smallint(6) NOT NULL default '0', `name` varchar(20) collate utf8_unicode_ci NOT NULL, PRIMARY KEY (`field_id`) ) -- Struktura tabulky `map_fields_specification` CREATE TABLE `map_fields_specification` ( `field_id` int(11) NOT NULL, `field_type` int(11) NOT NULL, PRIMARY KEY (`field_id`) ) -- Struktura tabulky `map_units_position` CREATE TABLE `map_units_position` ( `field_id` int(11) NOT NULL, `unit_type` int(11) NOT NULL, `x` int(11) NOT NULL, `y` int(11) NOT NULL, PRIMARY KEY (`field_id`,`unit_type`) )
-- Struktura tabulky `navy_map` CREATE TABLE `navy_map` ( `field1` int(11) NOT NULL, `field2` int(11) NOT NULL, PRIMARY KEY (`field1`,`field2`) )
37
-- Struktura tabulky `rounds` CREATE TABLE `rounds` ( `game_id` int(11) NOT NULL, `period` int(11) NOT NULL, `common_turns` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, `supplementary_turns` timestamp NULL default NULL, `add_units` timestamp NULL default NULL, `end` timestamp NULL default NULL, PRIMARY KEY (`game_id`,`period`) ) -- Struktura tabulky `supply_centres` CREATE TABLE `supply_centres` ( `position` int(11) NOT NULL, `field_id` int(11) NOT NULL, `standard_owner` int(11) NOT NULL, PRIMARY KEY (`position`) ) -- Struktura tabulky `thread_permissions` CREATE TABLE `thread_permissions` ( `thread_id` int(11) NOT NULL default '0', `permission` int(11) NOT NULL default '0', PRIMARY KEY (`thread_id`) ) -- Struktura tabulky `units` CREATE TABLE `units` ( `unit_id` int(11) NOT NULL auto_increment, `type` int(11) NOT NULL, `country_id` int(11) NOT NULL, `state` int(11) NOT NULL, PRIMARY KEY (`unit_id`) ) -- Struktura tabulky `units_details` CREATE TABLE `units_details` ( `unit_id` int(11) NOT NULL, `period` int(11) NOT NULL, `position` int(11) NOT NULL,
38
`action` int(11) NOT NULL, `destination` int(11) NOT NULL, `support_unit` int(11) NOT NULL, `suplementary_destination` int(11) NOT NULL, PRIMARY KEY (`unit_id`,`period`) ) -- Struktura tabulky `user_permissions` CREATE TABLE `user_permissions` ( `user_id` int(11) NOT NULL default '0', `permission` tinyint(4) NOT NULL default '0', PRIMARY KEY (`user_id`) ) -- Struktura tabulky `users` CREATE TABLE `users` ( `user_id` int(11) NOT NULL auto_increment, `nick` varchar(20) collate utf8_unicode_ci NOT NULL, `password` varchar(32) collate utf8_unicode_ci NOT NULL, `name` varchar(50) collate utf8_unicode_ci default NULL, `mail` varchar(100) collate utf8_unicode_ci NOT NULL, `inst_mess` varchar(50) collate utf8_unicode_ci default NULL, `sex` tinyint(1) NOT NULL, `reg_date` timestamp NOT NULL default CURRENT_TIMESTAMP, `last_login` timestamp NOT NULL default '0000-00-00 00:00:00', `online` tinyint(1) NOT NULL default '0', `selected_game` int(11) default NULL, `games` int(11) NOT NULL default '0', `wins` int(11) NOT NULL default '0', `draws` int(11) NOT NULL default '0', `losses` int(11) NOT NULL default '0', PRIMARY KEY (`user_id`) )
39
Příloha D: Veškeré zdrojové soubory jsou na přiloženém CD. Zdrojové kódy nejsou veřejné. Smí být použity pouze se souhlasem autora.
40