online textová hra - SPŠE, V Úžlabině 320, Praha 10

Transkript

online textová hra - SPŠE, V Úžlabině 320, Praha 10
Střední průmyslová škola elektrotechnická,
Praha 10, V Úžlabině 320
ONLINE TEXTOVÁ HRA
Praktická zkouška z odborných předmětů
Autor:
Jan Svatoš
Studijní obor:
26-47-M/002 Elektronické počítačové systémy
Třída:
E4.C
Školní rok:
2007/2008
Vedoucí práce:
Ing. Lenka Suchánková
Konzultant práce:
Lukáš Masopust
1 / 50
Čestné prohlášení:
“Prohlašuji, že jsem tuto práci vypracoval samostatně a použil jsem
literárních pramenů a informací, které cituji a uvádím v seznamu použité
literatury a zdrojů informací. Souhlasím s využitím díla pro školu.”
V Praze dne…………….
…………………………...
podpis autora (jméno a příjmení)
2 / 50
Anotace
Náplní práce je vytvořit on-line textovou hru s několika jednoduchými
grafickými prvky. Hra je vytvořena pro internetové prohlížeče, a tak je možné ji
hrát kdekoliv z jakéhokoliv počítače s přístupem na internet. Název hry je "The
Ages", neboli volně přeloženo "Staré časy". Účelem hry je spravovat svou
provincii, prosperovat, dobývat a konečně porazit Pána temnot a jeho armádu.
Hráč má na výběr různé jednotky a budovy, které se více čí méně liší. Hra je
tahová a jeden tah je přidán každých dvacet minut. To znamená, že hráč
nemusí u hry neustále sedět.
The goal of this is to create an on-line text-based game with a few simple
graphic things. The game is created for web browsers, so it can be played
anywhere with any computer with internet access. It is called "The Ages", or say
"The old ages". The goal of the game is to overlook your province, prosper,
conquer and finaly to defeat the Lord of darkness and his army. The player can
choose different types of units, which differs more or less. The game is turnbased and one turn is added for each twenty minutes. It means that the player
doesn't have to sit all the time by the computer and play the game.
3 / 50
Obsah
1. Zadání........................................................................................................................6
2. Teoretický rozbor.......................................................................................................8
2.1. Technologie.......................................................................................................8
2.2. Rozbor hry.........................................................................................................8
2.3. Pravidla hry.......................................................................................................9
3. Grafika.....................................................................................................................10
3.1. Rozvržení a obsah stránek.............................................................................10
3.1.1 Index.........................................................................................................10
3.1.2 Vytváření účtu...........................................................................................11
3.1.3 Přihlašování..............................................................................................12
3.1.4 Vlastní hra.................................................................................................12
3.1.5 Zápatí........................................................................................................13
3.2. CSS.................................................................................................................15
3.2.1 Obecně.....................................................................................................15
3.2.2 „Matrjoška“................................................................................................15
4. Vnitřní fungování hry & kódování............................................................................17
4.1. Struktury tabulek.............................................................................................17
4.1.1 Tabulka 'Provincie'....................................................................................17
4.1.2 Tabulka 'Posts'..........................................................................................21
4.1.3 Tabulka 'Buildings_Init'..............................................................................21
4.1.4 Tabulka 'Buildings'.....................................................................................23
4.1.5 Tabulka 'Units_Init'....................................................................................23
4.1.6 Tabulka 'Units'...........................................................................................25
4.1.7 Tabulka 'Equip_Init'...................................................................................25
4.1.8 Tabulka 'Equip'..........................................................................................26
4.2. Obecná funkce................................................................................................27
4.2.1 Vytvoření účtu...........................................................................................27
4.2.2 Přihlášení..................................................................................................28
4.2.3 Stavění budov...........................................................................................28
4.2.4 Bourání budov...........................................................................................29
4.2.5 Armáda......................................................................................................30
4.2.6 Zbrojnice...................................................................................................31
4.2.7 Pošta.........................................................................................................31
4.2.8 Provincie...................................................................................................32
4.3. Bojový systém.................................................................................................33
4.3.1 Popis.........................................................................................................33
4.3.2 Diagram....................................................................................................34
4.4. Funkce.............................................................................................................37
4.4.1 Connect.....................................................................................................37
4.4.2 Select........................................................................................................37
4.4.3 TableUpper & TableLower.........................................................................38
4.4.4 TailMenu....................................................................................................39
5. Závěr........................................................................................................................40
6. Zdroje.......................................................................................................................41
7. Přílohy......................................................................................................................42
7.1. Seznam příloh.................................................................................................42
4 / 50
1. Zadání
1.1. Vytvořte on-line textovou hru, ktera bude zahrnovat následující akce:
a) Registrace uživatelů
b) Validace registrace přes e-mail
c) Stavba a bourání budov
d) Těžba surovin
e) Výroba zbraní pro jednotky
f) Rekrutování armády
g) Vylepšování výzbroje (ozbrojování) jednotek armády
h) Boj mezi hráči
i) Pošta mezi hráči
1.2. Součástí práce bude manuál s návodem na ovládání a s pravidly hry
včetně názorných screenshotů obrazovek.
1.3. Pokyny pro vypracování:
1. Skripty a stylyl vytvářejte s pomocí freeware programu PSPad.
2. Hráč bude hru ovládat pomocí jednoduchých formulářů typu „počet
jednotek“ a „odeslat“.
3. Hra může umožnit tvorbu aliancí (sdružení více hráčů) a vzájemnou
podporu hráčů jedné aliance v podobě půjčování jednotek a posílání
surovin.
4. Ve hře je možno přidat aukci, kde budou jednotliví hráči prodávat a
kupovat své jednotky, suroviny, zbraně a půdu.
5. Layout bude vytvořen pomocí CSS a jen nezbytně nutné formuláře
tabulkami, bude graficky jednoduchý a nenáročný na oči (tmavé barvy) z
5 / 50
důvodu nočního či dlouhého hraní a převahy textu.
6. Vedle textových odkazů menu budou malé ikony těchto akcí.
7. Protokol maturitní práce bude splňovat formální náležitosti dle
http://skola.uzlabina.cz/dlouhodoba_maturita.
6 / 50
2. Teoretický rozbor
2.1. Technologie
Vzhledem k tomu, že jsem student, rozhodl jsem se použít Freeware
programy nebo Trial (volně stažitelné, časově omezené) verze placených
programů. Pro veškeré kódování jsem použil program PSPad, který umí
zvýrazňovat jak CSS, tak PHP a HTML syntax, což je velice výhodné pro snazší
orientaci v kódu při vývoji jakéhokoli projektu. Pro grafické zpracování jsem
použil studentskou verzi programu Adobe Photoshop 8.0. Testoval jsem v
prohlížečích Opera, FireFox a MS Internet Explorer 6.
2.2. Rozbor hry
Hru jsem zasadil do prostředí středověku, přesněji fantasy. Tomu
odpovídají názvy, typy a možnosti jednotek. Původně jsem chtěl vytvořit více
ras a povolání, ale vzhledem k náročnosti jsem vše zredukoval na rasu jednu a
povolání zrušil kompletně. Hráč tedy hraje za člověka a spravuje svou provincii.
Jednotek je více typů - kombinace pozemní / letecká a bojová / střelecká.
Jednotky se liší svou cenou, útokem, obranou, náročností na údržbu a mnoha
dalšími vlastnostmi detailně popsanými v kapitole 3.1.5 Struktura tabulky
'Units'. Hra je tvořena pomocí PHP skriptů a MySQL databáze. Hra je online,
tahová a je možné ji hrát z jakéhokoliv počítače s připojením na internet a
libovolným internetovým prohlížečem. Veškeré údaje se ukládají na jeden
server do databáze. Chtěl jsem vytvořit co možná nejflexibilnější a
nejpřístupnější systém, a tak jsem vytvořil celkem jednoduchou, ale efektivní
strukturu. Použil jsem dvě tabulky jak pro jednotky, tak pro budovy. To mi
dovoluje měnit pružně vlastnosti jednotek a budov, aniž bych jakkoliv měnil
skripty. Pro hráče a poštu mám tabulky zvlášť. Většinu kontrol a zpracování
informací řeším přes skript zpracuj.php, který je víceúčelový a dle zaslaného
parametru action vykoná vždy chtěnou operaci.
7 / 50
2.3. Pravidla hry
Následující výčet pravidel hry by měl zamezit nejčastějším problémům
s administrací a překračovaní zákonů ČR. S pravidly musí hráč souhlasit při
registraci nového účtu.
•
Hráč smí vlastnit pouze jednu provincii.
•
Hráč může hrát po neomezenou dobu.
•
Hráč je povinen upozornit na jakoukoliv odchylku od pravidel.
•
Herní účty jsou majetkem zřizovatele a hráčům jsou pouze propůjčeny
po dobu hraní.
•
Administrátoři si vyhrazují právo smazat, či jakkoliv upravit libovolný
účet v souladu s pravidly.
•
Administrátoři si vyhrazují právo změnit pravidla, přičemž budou hráči o
změnách informováni minimálně týden před uvedením v platnost.
•
Je zakázáno zneužívat chyb ve hře a napomáhání v tomto jiným
hráčům.
•
Je zakázáno jakkoliv urážet, napadat či zesměšňovat administrátory.
•
Je zakázáno propagovat jakýmkoliv způsobem rasismus či nacismus,
ať už jménem provincie, regenta, či zprávami v poště.
8 / 50
3. Grafika
3.1. Rozvržení a obsah stránek
Obecně jsou všechny stránky tvořeny ve stylu Hlavička - Tělo - Zápatí.
Jednotlivé části se mění a jsou stejné vždy pro jeden typ stránek - vytváření
účtu, přihlašování, nebo samotná hra. Barvy jsem volil tmavé, protože se mi líbí
a obsah mi pak připadá více ucelený a též protože to bylo uvedeno již v zadání
práce. Tlačítka hlavních akcí jsem vytvořil grafická, jelikož to lahodí oku, zvýší
kontrast a zlepší orientaci na stránkách.
3.1.1 Index
Zde je na místě hlavičky logo hry, které je na okrajích do ztracena
(působí nenásilně, zapadá do pozadí) a ústředním motivem je středověký
zdobený meč s odleskem.
Obr. 1: Logo hry
Jako tělo se zobrazí dva obrázky s grafickými tlačítky umožňujícími
výběr registrace, nebo přihlášení. Registrace je reprezentována obrázkem
pergamenu s brkem a přihlášení pak svazkem starých rezavých klíčů.
9 / 50
Obr. 2: Regsitrace a přihlášení
3.1.2 Vytváření účtu
Hlavička je stejná jako na indexu a zůstává po celý průběh vytváření
účtu a registrace. Na místě těla se zobrazuje postupně průběh vytváření účtu
a informace o stavu registrace.
Obr. 3: Registrační formulář
3.1.3 Přihlašování
Jako hlavičká zůstává logo a namísto registrace jsou v těle dvě
formulářová pole k zadání údajů pro přihlášení (jméno, heslo) a grafické
odesílací tlačítko.
10 / 50
Obr. 4: Přihlašovací formulář
3.1.4 Vlastní hra
V hlavičce se nachází upravené logo, grafické pozadí, údaje o hráči
(jméno, název provincie a rasa) a grafické tlačítko na odhlášení.
Obr. 5: Hlavička vlastní hry (zmenšeno)
Tělo je tvořeno informaci o množství surovin hráčovy provincie, textovým
menu s malými ikonami a pod ním obsahem dle vybrané akce z menu povětšinou tabulky a formulářová pole pro ovládání hry.
Obr. 6: Menu pro výběr akce
11 / 50
Obr. 7: Tabulka informací o provincii
3.1.5 Zápatí
Vyskytuje se na všech stránkách a obsahuje odkazy na vytvoření
účtu, přihlášení, pravidla a návod ke hraní. Dále je zde uveden autor, název
hry a vyhrazení práv na používání díla a jeho částí.
Obr. 8: Zápatí stránek
12 / 50
3.2. CSS
3.2.1 Obecně
Obecně jsem se snažil řešit vše relativním pozicováním (s absolutním
pozicováním jsou mnohdy problémy), obrázky pak pozadím v divu nebo
tabulce a veškeré úpravy textu přes css. To mi umožnilo pružně měnit vzhled
celých stránek, aniž bych musel vše několikrát přepisovat na různých
stránkách. Vytvořil jsem si též několik tlačítek přes css - pozadí a text se mění
údálostí hover.
Styl pro zmíněné tlačítko:
.utok_vypis
.utok_vypis:hover
{background-color: #2f2f2f; color: #afafaf;}
{background-color: #afafaf; color: #ffffff;}
3.2.2 „Matrjoška“
Vzhledem k designu a především rozvržení stránek, použil jsem tuto
metodu, pomocí níž jsem vytvořil jakýsi „obal“, který vše drží pohromadě.
Navíc pomáhá při odlaďování pro IE, protože používá jiný model zobrazení,
který počítá pro šířku i vlastnosti objektu - padding a border.
Úsek kódu s použitím této metody:
...
<div class="matrjoskamain">
<div class="main">
<div class="main-middle">
<div class="matrjoskaobsah">
<div class="obsah">
<div class="obsah-left">
<div class="ikony">
<?php
if($_SESSION['logged']==1){
provStat();
}
echo "</div>";
echo "</div>";
echo "<div class='obsah-main'>";
include "main.php";
?>
</div>
</div> <!-- end of obsah -->
13 / 50
</div> <!-- end of matrjoskaobsah -->
</div>
</div> <!-- end of main -->
</div> <!-- end of matrjoskamain -->
...
Styly pro jednotlivé divy „matrjošky“:
/* Matrjosky */
.matrjoskahlavni
{width: 850px; height: auto; padding: none;
margin: 0 auto 0 auto;}
.hlavni
{width: auto; height: auto; padding: none;
margin: 0 auto 0 auto; background-color: black;}
.matrjoskainfo
{width: 850px; height:auto; padding: none;
margin: 0 auto 0 auto;}
.infologout
{width: auto; height: 24px; padding: none;
margin: 0 auto 0 auto; background-color: black;}
.matrjoskamain-up
{width: 850px; height:auto; padding: none;
margin: 0 auto 0 auto; float: left;}
.main-up
{width: auto; height: 47px; padding: none;
margin: 0 auto 0 auto; background-color: black;}
.matrjoskamain
{width: 850px; height:auto; padding: none;
margin: 0 auto 0 auto; float: left;}
.main
{width: auto; height: auto; padding: none;
margin: 0 auto 0 auto; background-color: black;}
.matrjoskaobsah
margin: 0 auto 0 auto;}
.obsah
margin: 0 auto 0 auto;}
{width: 759px; height:auto; padding: none;
{width: auto; height: auto; padding: none;
.matrjoskamain-down
{width: 850px; height:auto; padding: none;
margin: 0 auto 0 auto; float:left;}
.main-down
{width: auto; height: 47px; padding: none;
margin: 0 auto 0 auto; background-color: black;}
14 / 50
4. Vnitřní fungování hry & kódování
4.1. Struktury tabulek
Zde jsou uvedeny jednotlivé tabulky a stručně vysvětlen význam
jednotlivých polí.
4.1.1 Tabulka 'Provincie'
Obsahuje informace o hráči (stavu jeho surovin, zbývající volné tahy, síla
provincie apod.).
Obr. 9: Struktura tabulky 'Provincie'
15 / 50
id: unikátní číslo každého hráče - klíč tabulky, automaticky inkrementovaný
player_name: jméno hráče
player_pass: heslo hráče
provincie_name: název hráčovy provincie
active: zdali je účet aktivovaný (přes e-mail), ANO=1, NE=0
activate_link: obsahuje unikátní generovaný aktivační klíč pro aktivaci přes email (více viz 4.2.1 Vytvoření účtu)
race: rasa hráče
turns_done: počet odehraných tahů
turns_left: volné zbývající tahy
room: půda k dispozici
gold, iron, stone, wood: aktuální stav surovin (zlato, železo, kámen, dřevo)
mana, population: aktuální stav many a velikosti populace
strength: síla provincie
buildingID: ID právě stavěné budovy
buildingCount: počet právě stavěných budov
builtTurns: kolik tahů již byla daná stavba stavěna
recrutingID: ID právě rekrutované jednotky
recrutingCount: počet právě rekrutovaných jednotek
recrutedTurns: pro vícetahové rekrutování jednotek - obdobně jako
builtTurns
last_action: pro přidávání tahů - údaj o poslední akci hráče
ms_overflow: pro přidávání tahů - infomace o necelém tahu
4.1.2 Tabulka 'Posts'
Obsahuje posílanou poštu mezi jednotlivými hráči ve hře.
Obr. 10: Struktura tabulky 'Posts'
16 / 50
id: unikátní číslo každé zprávy
IDfrom: od koho je zpráva obdržena
IDto: komu je zpráva určena
posted_on: kdy byla zpráva poslána
not_read: slouží k detekci nové pošty, přečteno=0, nová zpráva=1
body: tělo vlastní zprávy
4.1.3 Tabulka 'Buildings_Init'
Obsahuje údaje o budovách - jejich ceny, náročnost na údržbu, potřebné
suroviny, rasu, název budovy, kolik tahů trvá ji postavit atp. Je to 1 / 2 tabulek
potřebných pro budovy.
Obr. 11: Struktura tabulky 'Buildings_Init'
17 / 50
bid: unikátní číslo každé budovy
req_race: potřebná rasa
name: název budovy
req_gold, req_mana, req_population, req_wood, req_stone, req_iron,
req_room: potřebné hodnoty (zlato, mana, populace, dřevo, kámen, železo,
půda)
req_turns: počet tahů potřebný ke stavbě jedné budovy
req_bid: když je budová závislá na jiné budově, obsahuje její ID
req_bcount: když je budová závislá na jiné budově, obsahuje počet
potřebných budov, na kterých je závislá na jednu budovu
up_gold, up_mana ... : suroviny, které jedna budova spotřebuje za jeden tah
give_gold, give_mana ... : suroviny, které jedna budova přidá za jeden tah
4.1.4 Tabulka 'Buildings'
Relační tabulka, obsahuje závislosti mezi hráči a budovami - vyjadřuje,
kdo kterou budovu vlastní a kolikrát. Je to 2 / 2 tabulek potřebných pro
budovy.
Obr. 12: Struktura tabulky 'Buildings'
id: unikátní číslo každého záznamu v tabulce
bid: ID budovy
ownerid: ID vlastníka budovy
count: počet budov
name: název budovy
18 / 50
4.1.5 Tabulka 'Units_Init'
Obsahuje údaje o jednotkách - jejich ceny, náročnost na údržbu,
potřebné suroviny, rasu, název jednotky, kolik tahů trvá ji narekrutovat atp. Je
to 1 / 2 tabulek potřebných pro jednotky.
Obr. 13: Struktura tabulky 'Units_Init'
idu: unikátní číslo každé jednotky
req_race: potřebná rasa
type: název jednotky
req_gold, req_mana, req_pop, req_wood, req_stone, req_iron: potřebné
hodnoty (zlato, mana, populace, dřevo, kámen, železo)
req_turns: počet tahů potřebný k narekrutování jedné jednotky
req_buildingId: obsahuje ID budovy, kterou je nutno postavit, aby mohla být
jednotka narekrutována
19 / 50
up_gold, up_mana ... : suroviny, které spotřebuje jedna jednotka za jeden tah
att, def, ini, hp: parametry jednotek (síla, obrana, iniciativa, životy)
fly: zdali je jednotka letecká=1, pozemní=0
shooter: zdali je jednotka střelecká=1, bojová=0
weapon_id_can_handle: ID výzbroje, kterou může daná jednotka nosit
4.1.6 Tabulka 'Units'
Relační tabulka, obsahuje závislosti mezi hráči a jednotkami - vyjadřuje,
kdo kterou jednotku vlastní a kolikrát. Je to 2 / 2 tabulek potřebných pro
jednotky.
Obr. 14: Struktura tabulky 'Units'
id: unikátní číslo každého záznamu v tabulce
idu: ID jednotky
ownerid: ID vlastníka jednotky
count: počet jednotek
eq_count: počet ozbrojených jednotek
name: název jednotky
4.1.7 Tabulka 'Equip_Init'
Obsahuje údaje o výzbroji - jejich cenu, potřebné suroviny, rasu, název
výzbroje, kolik tahů trvá ji vyrobit atp. Je to 1 / 2 tabulek potřebných pro
výzbroj.
20 / 50
Obr. 15: Struktura tabulky 'Equip_Init'
eid: unikátní číslo každé výzbroje
name: název výzbroje
req_turns: počet tahů potřebný k vyrobení jedné výzbroje
m_att, m_def ... : modifikátory vlastností jednotek (+útok, +obrana atd.).
4.1.8 Tabulka 'Equip'
Relační tabulka, obsahuje závislosti mezi hráči a výzbrojí - vyjadřuje, kdo
má kterou výzbroj ve zbrojnici a kolikrát. Je to 2 / 2 tabulek potřebných pro
výzbroj.
Obr. 16: Struktura tabulky 'Equip'
id: unikátní číslo každého záznamu v tabulce
eid: ID výzbroje
ownerid: ID vlastníka výzbroje
count: počet kusů výzbroje, které má vlastník ve zbrojnici k dispozici
name: název výzbroje
21 / 50
4.2. Obecná funkce
4.2.1 Vytvoření účtu
Po vyplnění všech polí se odešlou informace na skript zpracuj.php, kde
se zkontroluje zda jsou pole jméno, název provincie, e-mail vyplněny, že hráč
souhlasí s pravidly hry a zda jsou pole heslo1 a heslo2 stejné a vyplněné.
Pokud ano, následuje kontrola, zda jsou použité názvy volné (jestli daná
osoba není registrovaná a nikdo nevlastní provincii se stejným názvem). Když
je vše v pořádku, skript pošle na zadanou adresu e-mail s informacemi o
registraci a přesměruje na skript registered.php, kde se zobrazí informace o
úspěšné registraci.
Úsek kódu, který obstará zaslání e-mailu:
//Email s pokyny k aktivaci
$message="Dobry den,<br /> vas ucet byl uspesne vytvoren.<br />";
$message.="Nyni prosim kliknete na nasledujici odkaz pro aktivaci
vaseho uctu.<br />";
$message.="<a
href='http://ages.mysteria.cz/registered.php?activate=$active_link_str
'>http://ages.mysteria.cz/registered.php?activate=$active_link_str</a>
";
mail($email,'Aktivace uctu na <ages.mysteria.cz>',$message,"ContentType: text/html; charset=iso-8859-1");
Po kliknutí na aktivační odkaz v e-mailu, je hráč přesměrován na skript
registered.php, kde se zobrazí informace, zda je daný účet aktivovaný
a registrace je tak dokončena. Nabídne též rovnou odkaz k přihlášení do hry.
Aktivační klíč vytvářím z ID hráče, jeho přezdívky a názvu jeho provincie. ID
hráče je unikátní, protože je nastavené jako klíč tabulky provincie s
parametrem auto_increment a proto celý aktivační klíč je též unikátní pro
každého registrovaného hráče.
22 / 50
4.2.2 Přihlášení
Po zadání jména a hesla se zkontroluje správnost přihlašovacích údajů
(jméno odpovídá heslu) na skriptu zpracuj.php a když jsou údaje v pořádku,
přesměruje již do hry na stránku design.php, která v sobě zahrnuje i skript
pro ovládání hry main.php. Přihlášení kontroluji přes proměnnou typu
SESSION. Všechna hesla jsou zakódována standardní funkcí PHP jednosměrným šifrováním MD5, jelikož to zvyšuje bezpečnost.
Příklad kontroly přihlášení:
if($_SESSION['logged']==1){
...kód...
}else{
header("location: login.php?err=3");
}
Nebo:
if(!$_SESSION['logged']==1){
header("location: login.php?err=3");
}
4.2.3 Stavění budov
Tato sekce obsahuje tabulku s informacemi o budovách, které je možno
stavět, nebo jsou již postaveny. Pod ní jsou buď formulářová pole na výběr
stavěné budovy a na žádaný počet postavených budov s tlačítkem na
odeslání příkazu ke stavění (na skript zpracuj.php), nebo výpis informací o
průběhu stavění budov. Pro výběr budovy používám dynamicky generovanou
roletku (formulářové pole select), jenž vytvářím ze záznamů v tabulce a
vypočteného počtu možných budov ke stavění. Názvy jednotlivých budov,
které je možno postavit, ukládám do dvou polí spolu s jejich bID. Při zadání
stavby (tlačítkem postavit) se informace zašlou na skript zpracuj.php, kde se
zkontroluje, zda je dostatek surovin na stavbu daných budov a když je, odečte
suroviny za stavbu a uloží do databáze pokyny ke stavění (pole buildingID a
buildingCount). Kolik která budova trvá tahů vychází z počtu postavených
dílen. Některé budovy jsou závislé na jiných budovách, tzn. je potřeba mít
postaven určitý počet budov, na kterých je budova závislá, abych mohl
postavit jednu budovu požadovaného typu.
23 / 50
Roletka na stavění:
echo "<form action='zpracuj.php?action=5' method='post'>";
echo "<select name='bid' class='selectpole'>";
for($i=0;$i<count($b_id_array);$i++){
if( ($b_can_build_array[$i]>0)||($b_can_build_array[$i]=='*') ){
echo "<option
value='".$b_id_array[$i]."'>".$b_name_array[$i]."(".$b_can_build_array
[$i].")";
}
}
echo "</select> x <input type='text' name='bcount' class='numbers'>";
echo "<input type='submit' value='postavit' class='butt'>";
echo "</form>";
4.2.4 Bourání budov
Sekce obsahuje tabulku s informacemi o již postavených budovách,
které je možno zbourat. Je zde vypsáno, kolik daná budova spotřebuje
surovin za tah a kolik surovin naopak přidá. Hráč tak získá lepší přehled o
hospodaření se surovinami a usnadní pak výběr budov ke zbourání. Pro lepší
orientaci jsem napsal funkci, která nahradí znak '0' za libovolný znak předaný
jako parametr. Místo nul se tak zobrazí např. '-' a je tak jasně vidět, jaké
suroviny budova spotřebovává. Pod tabulkou jsou formulářová pole k výběru
typu budovy ke zbourání a počtu bouraných budov. Pro výběr bourané budovy
používám dynamicky generovanou roletku (formulářové pole select), jenž
vytvářím ze záznamů v tabulce a počtu možných budov ke zbourání, což je
počet aktuálně postavených budov daného typu. Názvy jednotlivých budov,
které je možno zbourat, ukládám do dvou polí spolu s jejich bID, stejně jako u
stavění. Příkazy se odesílají na skript zpracuj.php, jsou zpracovány a
následuje přesměrování zpět do sekce bourání budov. Za zbourání jakékoliv
budovy nedostane hráč žádné suroviny zpět.
Funkce ReplaceZeros - záměna '0' za požadovaný znak:
//-------------------------------------------------------------------/*
*/function replaceZeros($char)
//-------------------------------------------------------------------{
global $up_gold,$up_wood,$up_stone,$up_iron,$up_mana,$up_pop;
global $give_gold,$give_wood,$give_stone,$give_iron,$give_mana,
$give_pop;
global $req_gold,$req_mana,$req_pop,$req_wood,$req_stone,$req_iron,
$req_building_id;
24 / 50
if($req_gold==0){
$req_gold=$char; }
if($up_gold==0){
$up_gold=$char; }
if($give_gold==0){
$give_gold=$char; }
if($req_mana==0){
$req_mana=$char; }
if($up_wood==0){
$up_wood=$char; }
if($give_wood==0){
$give_wood=$char; }
if($req_pop==0){
$req_pop=$char; }
if($up_stone==0){
$up_stone=$char; }
if($give_stone==0){
$give_stone=$char; }
if($req_wood==0){
$req_wood=$char; }
if($up_iron==0){
$up_iron=$char; }
if($give_iron==0){
$give_iron=$char; }
if($req_stone==0){
$req_stone=$char; }
if($up_mana==0){
$up_mana=$char; }
if($give_mana==0){
$give_mana=$char; }
if($req_iron==0){
$req_iron=$char; }
if($up_pop==0){
$up_pop=$char; }
if($give_pop==0){
$give_pop=$char; }
if($req_building_id==0){ $req_building_id=$char; }
return 1;
}
4.2.5 Armáda
Sekce obsahuje dvě tabulky - jedna s informacemi o jednotkách, které
má hráč ve své armádě a druhá s informacemi o jednotkách, které hráč může
narekrutovat do své armády. Je zde přehled, kolik jednotek daného typu
vlastním, kolik jednotky spotřebují surovin za tah, jakého jsou typu, jakou mají
sílu a kolik síly má hráč v daném typu jednotek. Pod první tabulkou jsou
formulářová pole pro propouštění jednotek a pod druhou na rekrutování. Pro
výběr jednotky používám dynamicky generovanou roletku (formulářové pole
select), jenž vytvářím z možných jednotek k rekrutování, což zjišťuji z počtu již
postavených rekrutovacích budov. Opět se příkazy odesílají na skript
zpracuj.php, jsou zpracovány a následuje přesměrování zpět do sekce
armády. Hráč může jednotky rekrutovat a propouštět. Propustit může libovolný
počet jednotek za tah, ale rekrutovat může jen tolik, kolik mu dovolí postavené
budovy odpovídajícího typu. Armáda je nejdůležitější prvek ve hře, respektive
její složení, protože veškerá konfrontace s ostatními hráči vede přes ni.
25 / 50
4.2.6 Zbrojnice
Sekce obsahuje dvě tabulky - jedna s počty výzbroje ve zbrojnici, kterou
je možno přiřadit odpovídajícím jednotkám (názvy odpovádajících jednotek
jsou též vypsány) a druhá s počty výzbroje již přiřazené jednotkám. U obou
tabulek je uveden i počet, kolik ještě může hráč jednotek odzbrojit či vyzbrojit.
Při propouštění se nejdříve propustí neozbrojené jednotky a až pak jednotky
ozbrojené. Pod oběma tabulkami se nachází formulářová pole k přiřazování a
odebírání výzbroje. Pro výběr výzbroje používám dynamicky generovanou
roletku (formulářové pole select), jež vytvářím z počtu výzbroje daného typu v
hráčově zbrojnici, nebo počtu výzbroje již přiřazené odpovídajícím jednotkám
a ID dané výzbroje. Tyto informace ukládám do dvou polí a následně vypisuji
jako prvky formulářového pole select. Příkazy se odesílají na skript
zpracuj.php, jsou zpracovány a následuje přesměrování zpět do sekce
zbrojnice. Ozbrojené jednotky mají své vlastnosti upravené dle modifikátorů
jednotlivé výzbroje, viz 4.1.7 Tabulka 'Equip_Init'. Tím je možno armádu
vylepšovat.
4.2.7 Pošta
Sekce obsahuje menu s položkami nová pošta, všechna pošta a poslat
zprávu. Hráč je po vybrání podsekce přesměrován na ten samý skript, s jinou
kontrolní proměnnou. Ta zajistí výběr požadované podsekce. Nová pošta zobrazí se jen dosud nepřečtená pošta, všechna pošta - zobrazí se vše a po
rozkliknutí podsekce poslat zprávu se zobrazí tabulka s výpisem všech
provincíí s možností poslat zprávu. Po vyplnění formuláře je hráč
přesměrován na skript zpracuj.php, kde se vyhodnotí zaslané informace a
případně vloží nový záznam do tabulky Posts.
Následující skript obstarává zaslání pošty (zpracuj.php):
//-------------------------------------------------------------------//--- Posli zpravu --------------------------------------------------//-------------------------------------------------------------------if($action=='sendmail'){
Connect();
$idto=$_POST['idto'];
$idfrom=$_POST['idfrom'];
26 / 50
$body=$_POST['body'];
if($idto>0){
$q=mysql_query("INSERT INTO posts
VALUES('','$idfrom','$idto',NOW(),'1','".htmlspecialchars($body)."')",
$connection);
if($q>0){
header('location: design.php?action=5&msg=sent');
}else{
header('location: design.php?action=5&msg=error');
}
}else{
header('location: design.php?action=5&msg=warning');
}
}
Jeho funkční ekvivalent pro fight.php:
function sendmail($idto,$idfrom,$body){
global $connection;
if($idto>0){
$q=mysql_query("INSERT INTO posts
VALUES('','$idfrom','$idto',NOW(),'1','$body')",$connection);
return mysql_affected_rows($connection);
}else{
return 0;
}
}
4.2.8 Provincie
Sekce obsahuje výpis provincií, na které je možno útočit. Provincie jsou
v rozmezí síly ±25% od stávající síly hráčovy provincie (tzn. 75% až 125%
stávající síly). Toto omezení jsem zavedl pro lepší hratelnost a férovost hry,
navíc útok na provincii se sílou dvakrát větší, než má hráč, se rovná
sebevraždě.
27 / 50
4.3. Bojový systém
4.3.1 Popis
Pro bojový systém jsem zvolil práci s třídami. Ty umožňují, dle mého
názoru, nejkratši kód a efektivní práci s proměnnými. Každá jednotka je tak
zvlášť a jsou pro ni načteny její vlastnosti - útok, obrana, přítel / nepřítel atd.
Zde je ukázka deklarace třídy Stack (jednotky jednoho typu):
//----TRIDA STACK----------------------------------------------------class stack {
var $att,$def,$ini,$hp,$fly,$shooter,$name;
var $eq_count;
var $id,$idu;
var $used_this_turn,$enemy;
var $m_att,$m_def,$m_ini,$m_hp,$m_fly,$m_shooter;
function stack($id,$idu,$count,$eq_count,$enemy){
$this->id=$id;
$this->idu=$idu;
$this->eq_count=$eq_count;
$this->count=$count;
$this->enemy=$enemy;
$this->used_this_turn=0;
}
function getStackStats(){
$idu=$this->idu;
$sq=select("att,def,ini,hp,fly,shooter,type","units_init","idu=$
idu");
list($att,$def,$ini,$hp,$fly,$shooter,$name)=fetch($sq);
$this->att=$att;
$this->def=$def;
$this->ini=$ini+$shooter*1000;
$this->hp=$hp;
$this->fly=$fly;
$this->shooter=$shooter;
$this->name=$name;
}
function getStackEqStats(){
$eid=getEqIdToUnit($this->id);
$eq=select("m_att,m_def,m_ini,m_hp,m_fly,m_shooter","equip_init"
,"eid=$eid LIMIT 1");
if($eq>0){
while(
list($m_att,$m_def,$m_ini,$m_hp,$m_fly,$m_shooter)=fetch($eq) ){
$this->m_att=$m_att;
$this->m_def=$m_def;
$this->m_ini=$m_ini;
$this->m_hp=$m_hp;
28 / 50
$this->m_fly=$m_fly;
$this->m_shooter=$m_shooter;
}
}
}
function setCount($count){
$this->count=$count;
}
function resetTurn(){
$this->used_this_turn=$used_this_turn;
}
}
//----KONEC TRIDY STACK---------------------------------------------
Jak je vidno z ukázky, používám funkce deklarované pro třidu Stack, pro
nastavení vlastností, počtu, jestli již útočil, zkrátka veškeré operace s objekty
třídy Stack řeším přes funkce.
4.3.2 Diagram
Pro větší přehlednost a lepší pochopení přikládám místo slovního popisu
obecný diagram bojového systému, ze kterého by mělo být fungování jasné.
29 / 50
Obr. 17: Diagram bojového systému
30 / 50
4.4. Funkce
Zde popíšu několik užitečných a často používaných funkcí, které jsem
napsal, abych si ulehčil práci a zpřehlednil si kód.
4.4.1 Connect
Velice užitečná funkce, volám ji mnohokrát, dokonce snad na každé
stránce. Jak už vyplývá z názvu, slouží k připojení k MySQL databázi, navíc
nastaví UTF-8 komunikaci mezi skriptem a databází. Funkce nemá žádný
parametr. Pokud se nepodaří vytvořit spojení, přeruší provádění skriptu
přikazem die a vypíše chybovou hlášku, jinak vybere konkrétní databázi na
předloženém serveru.
//-------------------------------------------------------------------/*
*/function Connect(){
//-------------------------------------------------------------------$con_server="mysql.webzdarma.cz";
$con_name="ages16";
$con_db="ages16";
$con_pass="!123654";
global $connection;
$connection=mysql_connect($con_server,$con_name,$con_pass);
@mysql_query("SET NAMES UTF8");
if(!$connection){
die("Error. ".mysql_error() );
}else{
mysql_select_db($con_db,$connection);
}
return 1;
}
4.4.2 Select
Velmi užitečná funkce, slouží k výběru dat z tabulky pomocí MySQL
příkazu SELECT. Je zde možnost tzv. debugu, což umožňuje vypsat příkaz
vykonávaný databází. To se moc hodí při odlaďování. Funkce má jako
parametr tři proměnné - str1, str2 a str3. Jejich význam je sloupec, tabulka,
podmínka. Jak vidno, značně to ulehčí práci při psaní příkazů typu SELECT.
Funkce vrací výsledek dotazu na MySQL databázi.
31 / 50
//-------------------------------------------------------------------/*
*/function select($str1,$str2,$str3)
//-------------------------------------------------------------------{
global $connection;
global $debug;
if($debug==1){
echo "<br /><font color='#afafaf' size='-1'>SELECT $str1 FROM
$str2 WHERE $str3</font><br />";
}
return mysql_query("SELECT $str1 FROM $str2 WHERE
$str3",$connection);
}
4.4.3 TableUpper & TableLower
Tyto dvě funkce používám k vytvoření grafických okrajů kolem kódu
obsaženém v nich. Tvoří je jen PHP příkazy echo, které vytvoří tabulku, kde
jsou na pozadí jednotlivých divů obrázky tenkých linek. Vytvoří se tak grafický
obal daného obsahu.
//-------------------------------------------------------------------/*
*/function tableUpper(){
//-------------------------------------------------------------------echo("<table class='okolo' border='0' cellpadding='0'
cellspacing='0'>");
echo("<tr>");
echo("<td colspan='3'>");
echo("<div class='up'>");
echo("<div class='up-left'></div>");
echo("<div class='up-right'></div>");
echo("</div>");
echo("</td>");
echo("</tr>");
echo("<tr>");
echo("<td class='lefttable'>");
echo("</td>");
echo("<td>");
}
return 1;
//-------------------------------------------------------------------/*
*/function tableLower(){
//-------------------------------------------------------------------echo("</td>");
echo("<td class='righttable'>");
echo("</td>");
echo("</tr>");
echo("<tr>");
echo("<td colspan='3'>");
echo("<div class='down'>");
echo("<div class='down-left'></div>");
echo("<div class='down-right'></div>");
32 / 50
echo("</div>");
echo("</td>");
echo("</tr>");
echo("</table>");
}
return 1;
4.4.4 TailMenu
Tuto funkci vkládám (volám) na konci každé stránky a dělá to, že zobrazí
ocas stránky - menu, ve kterém je na výběr odkaz na registraci, přihlášení,
pravidla hry a návod ke hraní.
//-------------------------------------------------------------------/*
*/function tailMenu(){
//-------------------------------------------------------------------echo "<div class='tailmenu'>";
echo "<table align='center'>";
echo "<tr><td height='80px'>";
echo "<br />";
echo "<a href='register.php'>Registrace</a> | <a
href='login.php'>Login</a> | <a href='rules.php'>Pravidla</a> | <a
href='help.php'>Jak hrát</a><br />";
echo "<img src='img/linka.png' /><br />";
echo "<span style='font-size: 11px; color: #707070;'>Copyright ©
Langosh 2008, AGES:Another webgame<br />";
echo "Kopírování či použití jakékoli části webu bez autorova souhlasu
je zakázáno.</span>";
echo "</td></tr></table>";
echo "</div>";
}
33 / 50
5. Závěr
S prací jsem spokojen a myslím si, že za tak krátký časový úsek jsem
vytvořil vcelku komplexní a hlavně hratelnou hru. Hra je přístupná na adrese
http://www.ages.mysteria.cz.
Práce na tomto projektu mi přinesla mnoho nových poznatků a zkušeností,
které bych jinak možná nezískal a navíc jsem se v průběhu docela bavil. Vybral
jsem si téma, které je mi blízké, a tak šla práce vcelku od ruky. Během práce
jsem narazil na několik menších i závažnějších problémů, které jsem ale vždy
po chvíli přemýšlení byl schopen překonat vlastními prostředky. Zabralo to
mnoho času, ale nelituji té ztráty, již teď vidím, že se to vyplatilo. Získal jsem
dobrou znalost PHP programování, CSS stylování a práce s MySQL databází,
což mi může být v budoucnu velice prospěšné. Také bych rád uplatnil získané
znalosti na podobný projekt, ale nechal bych si více času na vývoj a
propracování jednotlivých částí.
34 / 50
6. Zdroje
Philip Olson © 1997-2007 the PHP Documentation Group - PHP manual [online]
[25.11.2007]
Dostupný z WWW: <http://www.php.net/manual/en/>
VAŠČÁK, Vladimír - PHP třídy a objekty [online]
Dostupný z WWW: <http://www.spszl.cz/~vascak/moje/ikt/php/php03.html>
Refsnes Data - CSS Tutorial [online]
Dostupný z WWW: <http://www.w3schools.com/css/>
JANOVSKÝ, Dušan - CSS - Kaskádové styly
[14.1.2008]
Dostupný z WWW: <http://www.jakpsatweb.cz/css/>
JANOVSKÝ, Dušan - HTML příručka, přehled HTML tagů
[14.1.2008]
Dostupný z WWW: <http://www.jakpsatweb.cz/html/>
35 / 50
7. Přílohy
Kvůli náročnosti tisku jsou zde rozepsány jen některé skripty. Vybral jsem
stěžejní část, aby bylo možno alespoň rámcově práci prohlédnout a bylo jasné,
že vím, co dělám. Všechny skripty jsou k dispozici na přiloženém CD-ROM.
7.1. Seznam příloh
1) Index.php
2) Design.php
3) Zpracuj.php
4) Style.css
Příloha č.1: Index.php
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="cs" lang="cs">
<head>
<title>The Ages :: [Index]</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<?php
require "functions.php";
?>
<div class="login" style='height: 460px;'>
<div class="loginramec">
<div class="logininner">
<table class='' cellspacing="0" cellpadding="0" align="center"
width="410">
<tr>
<!--<td style='height: 50px;' colspan='2'>asdfasdfasfd</td>-->
<td style='background: url("img/registrace.png"); width: 201px;
height: 166px;'></td>
<td style='background: url("img/klice.jpg"); width: 201px; height:
166px;'></td>
</tr>
<tr>
<td>
<div class="loginbutt" style='margin-left: 30px;'>
<form action="register.php" method="post">
<div class="leftbut"></div>
<input type="submit" value="&nbsp;"
class="buttok2">
<div class="rightbut"></div>
36 / 50
</form>
</div>
</td>
<td>
<div class="loginbutt" style='margin-left: 40px;'>
<form action="login.php" method="post">
<div class="leftbut"></div>
<input type="submit" value="&nbsp;" class="buttok">
<div class="rightbut"></div>
</form>
</div>
</td>
<div class="loginlogin"></div>
</tr>
</table>
</div>
</div>
</div>
<?php tailMenu(); ?>
</body>
</html>
Příloha č.2: Design.php
<?php
session_start();
include "functions.php";
Connect();
if (!$connection) {
echo "CHYBA SPOJENI: ".mysql_error();
die();
}
if($_SESSION['logged']==1){
$action=$_REQUEST['action'];
$p_id=$_SESSION['loggedID'];
$p_race_prov_query=selectp("race,provincie_name,player_name
","id=$p_id",$connection);
list($p_race,$p_province,$p_name)=mysql_fetch_row($p_race_prov_query);
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="cs" lang="cs">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta name="generator" content="nceo">
<link rel="stylesheet" type="text/css" href="style.css">
<title><?php echo "The Ages :: ".$_SESSION['loggedNAME']."@$p_province" ?></title>
</head>
<body>
37 / 50
<div class="matrjoskahlavni">
<div class="hlavni">
<div class="header"></div>
<div class="matrjoskainfo">
<div class="infologout">
<div class="info-left"></div>
<div class="info-info">
<!-- vytahnout z DB info -->
<?php
echo "<span class='info-jmeno'> $p_name</span>";
echo "<span class='info-provincie'> $p_province</span>";
if($p_race=='human'){ $p_race_str='Člověk'; }else{
$p_race_str='Nemrtvý'; }
echo "<span class='info-rasa'> $p_race_str</span>";
?>
</div>
<div class="info-logout"><a href="zpracuj.php?action=3"><img
class="logoutimage" src="img/info-logout.jpg" /></a></div>
<div class="info-right"></div>
</div> <!-- end of infologout -->
</div> <!-- end of matrjoskainfo -->
<div class="under-header"></div>
<div class="matrjoskamain-up">
<div class="main-up">
<div class="main-up-left"></div>
<div class="main-up-middle"></div>
<div class="main-up-right"></div>
</div> <!-- end of main-up -->
</div> <!-- end of matrjoskamain-up -->
<div class="matrjoskamain">
<div class="main">
<div class="main-middle">
<div class="matrjoskaobsah">
<div class="obsah">
<div class="obsah-left">
<div class="ikony">
<?php
if($_SESSION['logged']==1){
provStat();
}
echo "</div>";
echo "</div>";
echo "<div class='obsah-main'>";
38 / 50
include "main.php";
?>
</div>
</div> <!-- end of obsah -->
</div> <!-- end of matrjoskaobsah -->
</div>
</div> <!-- end of main -->
</div> <!-- end of matrjoskamain -->
<div class="matrjoskamain-down">
<div class="main-down">
<div class="main-down-left"></div>
<div class="main-down-middle"></div>
<div class="main-down-right"></div>
</div> <!-- end of main-down -->
</div> <!-- end of matrjoskamain-down -->
</div> <!-- end of hlavni -->
</div> <!-- end of matrjoskahlavni -->
<?php tailMenu(); ?>
</body>
</html>
Příloha č.3: Zpracuj.php
<?php
session_start();
$action=$_REQUEST['action'];
$p_id=$_SESSION['loggedID'];
require "functions.php";
//----------------------------------------------------------------------------//----Create province --------------------------------------------------------//----------------------------------------------------------------------------if($action==1){
$nick=$_REQUEST['nick'];
$prov_name=$_REQUEST['prov_name'];
$pass1=$_REQUEST['pass1'];
$pass2=$_REQUEST['pass2'];
$email=$_REQUEST['email'];
$race=$_REQUEST['race'];
$souhlas=$_REQUEST['souhlas'];
39 / 50
$error=0;
if ($nick==''){ $error=1; }
if ($prov_name==''){ $error=1; }
if ($email==''){ $error=1; }
if ($pass1==''){ $error=1; }
if ($pass1<>$pass2){ $error=2; }
if (!($souhlas=='on')){ $error=5; }
Connect();
//je jmeno hrace volne?
$q=mysql_query("SELECT id FROM provincie WHERE
player_name='$nick'",$connection);
while(list($id)=mysql_fetch_row($q) ){
$error=3;
}
//je jmeno provincie volne?
$q=mysql_query("SELECT id FROM provincie WHERE
provincie_name='$prov_name'",$connection);
while(list($id)=mysql_fetch_row($q) ){
$error=4;
}
if($error>0){
header("location:
register.php?error=".$error."&nick=".$nick."&prov_name=".$prov_name."&email=".$emai
l);
}else{
$pass_str=MD5($pass1);
//Nove upravy provincie resit zde
$q=mysql_query("INSERT INTO provincie
VALUES('','$nick','$pass_str','$prov_name','0','insert_a_link','$race','0','500','1
00','10000','10000','10000','10000','10000','2000','0','0','0','0','0','0','0','0',
'0')",$connection);
//Generovani unikatniho aktivacniho kodu
$q=mysql_query("SELECT id FROM provincie WHERE player_name='$nick' LIMIT
1",$connection);
list($id)=mysql_fetch_row($q);
$active_link=$id+$nick+$prov_name;
$active_link_str=MD5($active_link);
//Ulozeni..
$q=mysql_query("UPDATE provincie SET activate_link='$active_link_str' WHERE
id='$id' and active='0' LIMIT 1");
//Email s pokyny k aktivaci
$message="Dobry den,<br /> vas ucet byl uspesne vytvoren.<br />";
$message.="Nyni prosim kliknete na nasledujici odkaz pro aktivaci vaseho
uctu.<br />";
$message.="<a
href='http://ages.mysteria.cz/registered.php?activate=$active_link_str'>http://ages
.mysteria.cz/registered.php?activate=$active_link_str</a>";
mail($email,'Aktivace uctu na <ages.mysteria.cz>',$message,"Content-Type:
text/html; charset=iso-8859-1");
$error=mysql_error();
if($error==0){ header("location: registered.php"); }
}
mysql_close($connection);
}
//----------------------------------------------------------------------------//----Login -------------------------------------------------------------------
40 / 50
//----------------------------------------------------------------------------if($action==2){
$nick=$_REQUEST['nick'];
$nick=htmlspecialchars($nick);
$pass=$_REQUEST['pass'];
if ($nick==''){ header("location: login.php?err=1&nick=$nick"); }
$pass_str=MD5($pass);
Connect();
$q=mysql_query("SELECT id,player_name FROM provincie WHERE
player_name='".$nick."' AND player_pass='".$pass_str."' AND active='1' LIMIT 1");
list($id,$player_name)=mysql_fetch_row($q);
//Byl nalezen uzivatel s odpovidajicimi udaji?
if(mysql_num_rows($q)>0){
$_SESSION['logged']=1;
//Prihlas ho
$_SESSION['loggedID']=$id;
$_SESSION['loggedNAME']=$player_name;
mysql_close($connection);
header("location: design.php");
}else{
mysql_close($connection);
header("location: login.php?err=1&nick=$nick");
}
}
//----------------------------------------------------------------------------//----LogOut ------------------------------------------------------------------//----------------------------------------------------------------------------if($action==3){
unset($_SESSION['logged']);
unset($_SESSION['loggedID']);
unset($_SESSION['loggedNAME']);
header("location: login.php?err=2");
}
//----------------------------------------------------------------------------//----Chci stavet $building_id------------------------------------------------//----------------------------------------------------------------------------if($action==5){
//checkPlayer();
$b_id=$_POST['bid'];
$b_count=$_POST['bcount'];
//Abych nemohl stavet 0 a -1 budov
if($b_count>0){
Connect();
$stats_q=selectp("turns_left,gold,mana,population,iron,stone,wood,room","id='$p
_id'",$connection);
list($p_turns_left,$p_gold,$p_mana,$p_population,$p_iron,$p_stone,$p_wood,$p_ro
om)=mysql_fetch_row($stats_q);
//load info o stavene budove
$req_query=select("req_gold,req_mana,req_population,req_wood,req_stone,req_iron
,req_room,req_bid,req_bcount","buildings_init","bid=$b_id");
list($req_gold,$req_mana,$req_population,$req_wood,$req_stone,$req_iron,$req_
41 / 50
room,$req_bid,$req_bcount)=mysql_fetch_row($req_query);
$passed=1;
if($p_gold<($b_count*$req_gold) ){ $passed=0; echo "1";}
if($p_mana<($b_count*$req_mana) ){ $passed=0; echo "2";}
if($p_population<($b_count*$req_population) ){ $passed=0; echo "3";}
if($p_wood<($b_count*$req_wood) ){ $passed=0; echo "4
$p_wood<($b_count*$req_wood)";}
if($p_stone<($b_count*$req_stone) ){ $passed=0; echo "5";}
if($p_iron<($b_count*$req_iron) ){ $passed=0; echo "6";}
if($p_room<($b_count*$req_room) ){ $passed=0; echo "7";}
if(!$passed){
Close();
header("location: design.php?action=1&msg=2");
}else{
//Uber penize za stavby ( na zacatku )
$p_curr_gold=$p_gold-($b_count*$req_gold);
$p_curr_mana=$p_mana-($b_count*$req_mana);
$p_curr_pop=$p_population-($b_count*$req_population);
$p_curr_iron=$p_iron-($b_count*$req_iron);
$p_curr_stone=$p_stone-($b_count*$req_stone);
$p_curr_wood=$p_wood-($b_count*$req_wood);
$p_curr_room=$p_room-($b_count*$req_room);
$update_player_data_str="gold='$p_curr_gold',mana='$p_curr_mana',population='
$p_curr_pop',iron='$p_curr_iron',stone='$p_curr_stone',wood='$p_curr_wood',room='$p
_curr_room'";
$update_player_data_q=mysql_query("UPDATE provincie SET
$update_player_data_str WHERE id='$p_id' LIMIT 1",$connection);
$q=mysql_query("UPDATE provincie SET
buildingID='$b_id',buildingCount='$b_count' WHERE id=$p_id LIMIT 1",$connection);
Close();
header("location: design.php?action=1&msg=3");
}
}else{
//Pocet staveb < 1
header("location: design.php?action=1&msg=4");
}
}
//----------------------------------------------------------------------------//--- Cancel building --------------------------------------------------------//----------------------------------------------------------------------------if($action==6){
//checkPlayer();
Connect();
$q=select("buildingID,buildingCount","provincie","id=$p_id LIMIT 1");
list($b_id,$b_count)=fetch($q);
//Load player data
$stats_q=selectp("turns_left,gold,mana,population,iron,stone,wood,room","id='$p_i
d'",$connection);
list($p_turns_left,$p_gold,$p_mana,$p_pop,$p_iron,$p_stone,$p_wood,$p_room)=mys
ql_fetch_row($stats_q);
//load info o drive stavene budove
$req_query=select("req_gold,req_mana,req_population,req_wood,req_stone,req_iron,r
eq_room,req_bid,req_bcount","buildings_init","bid=$b_id");
42 / 50
list($req_gold,$req_mana,$req_pop,$req_wood,$req_stone,$req_iron,$req_room,$r
eq_bid,$req_bcount)=mysql_fetch_row($req_query);
$p_curr_gold=$p_gold+(0.25*$b_count*$req_gold);
$p_curr_mana=$p_mana+(0.25*$b_count*$req_mana);
$p_curr_pop=$p_pop+(0.25*$b_count*$req_pop);
$p_curr_iron=$p_iron+(0.25*$b_count*$req_iron);
$p_curr_stone=$p_stone+(0.25*$b_count*$req_stone);
$p_curr_wood=$p_wood+(0.25*$b_count*$req_wood);
$p_curr_room=$p_room+($b_count*$req_room);
$update_player_data_str="gold='$p_curr_gold',mana='$p_curr_mana',population='$p_c
urr_pop',iron='$p_curr_iron',stone='$p_curr_stone',wood='$p_curr_wood',room='$p_cur
r_room'";
$update_player_data_q=mysql_query("UPDATE provincie SET $update_player_data_str
WHERE id='$p_id' LIMIT 1",$connection);
$q=mysql_query("UPDATE provincie SET
buildingID='0',buildingCount='0',builtTurns='0' WHERE id=$p_id LIMIT
1",$connection);
header("location: design.php?action=1&msg=5");
}
//----------------------------------------------------------------------------//--- Bourani ----------------------------------------------------------------//----------------------------------------------------------------------------if($action=='bourat'){
$b_id=$_POST['bid'];
$b_destroy_count=$_POST['bcount'];
Connect();
$q=select("count","buildings","bid='$b_id' AND ownerid='$p_id' LIMIT 1");
list($b_count)=fetch($q);
$b_count-=$b_destroy_count;
if($b_count>0){
$q=mysql_query("UPDATE buildings SET count='$b_count' WHERE bid=$b_id AND
ownerid='$p_id' LIMIT 1",$connection);
}else{
$q=mysql_query("DELETE FROM buildings WHERE bid=$b_id AND ownerid='$p_id' LIMIT
1",$connection);
}
$destroyed=$b_destroy_count;
Close();
header("location: design.php?action=4&bdestroyed=$destroyed");
}
//----------------------------------------------------------------------------//--- Chci rekrutovat --------------------------------------------------------//----------------------------------------------------------------------------if($action=='rekrutovat'){
Connect();
$u_id=$_POST['uid'];
$u_count=$_POST['ucount'];
//Načtení ID potřebné budovy
$req_building_id_q=select("req_buildingId","units_init","idu='$u_id'");
list($req_building_id)=fetch($req_building_id_q);
43 / 50
//Načtení počtu postavených budov potřebných k výrobě jednotky
$req_buildings_owned_q=select("count","buildings","ownerid='$p_id' AND
bid='$req_building_id'");
list($req_buildings_owned)=fetch($req_buildings_owned_q);
echo $req_building_id."x".$req_buildings_owned;
//Kdyz vlastnim aspon jednu budovu potrebnou na jednotku
if($req_buildings_owned>0){
$q=mysql_query("UPDATE provincie SET
recrutingID='$u_id',recrutingCount='$u_count' WHERE id='$p_id' LIMIT
1",$connection);
Close();
//Ok
header("location: design.php?action=2&msg=1");
}else{
Close();
//Neproslo
header("location: design.php?action=2&msg=2");
}
}
//----------------------------------------------------------------------------//--- Cancel recruit ---------------------------------------------------------//----------------------------------------------------------------------------if($action=='zrusitrec'){
Connect();
$q=mysql_query("UPDATE provincie SET recrutingID='0',recrutingCount='0' WHERE
id=$p_id LIMIT 1",$connection);
Close();
header("location: design.php?action=2");
}
//----------------------------------------------------------------------------//--- Propust jednotky -------------------------------------------------------//----------------------------------------------------------------------------if($action=='propustit'){
$u_id=$_POST['uid'];
$u_dismiss_count=$_POST['ucount'];
Connect();
$u_count=getUnitCount($u_id);
$eq_count=getEqUnitCount($u_id);
$u_count-=$u_dismiss_count;
$new_eq_count=min($u_count,$eq_count);
$new_eq_count=max($new_eq_count,0);
if($u_count>0){
$q=mysql_query("UPDATE units SET count='$u_count', eq_count='$new_eq_count'
WHERE idu=$u_id AND ownerid='$p_id' LIMIT 1",$connection);
}else{
$q=mysql_query("DELETE FROM units WHERE idu=$u_id AND ownerid='$p_id' LIMIT
1",$connection);
}
Close();
header("location: design.php?action=2");
}
44 / 50
//----------------------------------------------------------------------------//--- Ozbroj jednotky --------------------------------------------------------//----------------------------------------------------------------------------if($action=='ozbrojit'){
Connect();
$eid=$_POST['eid'];
$ecount=$_POST['ecount'];
$ecount=max(0,$ecount);
if( $ecount>0 ){
$e_owned=getEqCount($eid);
$idu=getUnitIdToEq($eid);
$u_count=getUnitCount($idu);
$u_eq_count=getEqUnitCount($idu);
$u_can_eq=$u_count-$u_eq_count;
//Pokud mam dostatek vyzbroje a pokud jich tolik vubec muzu vyzbrojit
if( ($e_owned>=$ecount)&&($ecount<=$u_can_eq) ){
//Pridej vyzbroj jednotkam
$new_u_eq_count=$u_eq_count+$ecount;
$q=mysql_query("UPDATE units SET eq_count='$new_u_eq_count' WHERE
ownerid=$p_id AND idu=$idu",$connection);
//Uber vyzbroj ve zbrojnici
$new_e_owned=$e_owned-$ecount;
if($new_e_owned>0){
$q=mysql_query("UPDATE equip SET count='$new_e_owned' WHERE ownerid=$p_id
AND eid=$eid",$connection);
}else{
$q=mysql_query("DELETE FROM equip WHERE ownerid=$p_id AND
eid=$eid",$connection);
}
Close();
header("location: design.php?action=3&msg=ozbrojeno");
}else{
Close();
header("location: design.php?action=3&msg=nelze_ozbrojit");
}
}else{
Close();
header("location: design.php?action=3&msg=nelze_ozbrojit");
}
}
//----------------------------------------------------------------------------//--- Odzbroj jednotky -------------------------------------------------------//----------------------------------------------------------------------------if($action=='odzbrojit'){
Connect();
$eid=$_POST['eid'];
$ecount=$_POST['ecount'];
$ecount=max(0,$ecount);
if( $ecount>0 ){
$idu=getUnitIdToEq($eid);
$eq_count=getEqUnitCount($idu);
45 / 50
if( $eq_count>=$ecount ){
$new_eq_count=$eq_count-$ecount;
$q=mysql_query("UPDATE units SET eq_count='$new_eq_count' WHERE ownerid=$p_id
AND idu=$idu",$connection);
$already_have=getEqCount($eid);
if( $already_have>0 ){
$new_p_eq_count=$already_have+$ecount;
$q=mysql_query("UPDATE equip SET count='$new_p_eq_count' WHERE
ownerid=$p_id AND eid=$eid",$connection);
}else{
$eq_name=getEqName($eid);
$q=mysql_query("INSERT INTO equip
VALUES('','$eid','$p_id','$ecount','$eq_name')",$connection);
}
Close();
header("location: design.php?action=3&msg=odzbrojeno");
}else{
Close();
header("location: design.php?action=3&msg=nelze_odzbrojit");
}
}else{
Close();
header("location: design.php?action=3&msg=nelze_odzbrojit");
}
//post - kolik toho chci a co = eq-count, eq-id
//zjistit, kolik mam ozbrojenejch a jesi teda muzu tolik pripsat do equip
playerovi
//pokud to projde, zapis do DB - --units.eq_count / ++equip.count
//pokud ne, vyfakni
}
//----------------------------------------------------------------------------//--- Posli zpravu -----------------------------------------------------------//----------------------------------------------------------------------------if($action=='sendmail'){
Connect();
$idto=$_POST['idto'];
$idfrom=$_POST['idfrom'];
$body=$_POST['body'];
if($idto>0){
$q=mysql_query("INSERT INTO posts
VALUES('','$idfrom','$idto',NOW(),'1','".htmlspecialchars($body)."')",$connection);
//if(mysql_affected_rows($connection)>0 ){
if($q>0){
header('location: design.php?action=5&msg=sent');
}else{
header('location: design.php?action=5&msg=error');
}
}else{
header('location: design.php?action=5&msg=warning');
}
}
//----------------------------------------------------------------------------//--- Smaz zpravu ------------------------------------------------------------//----------------------------------------------------------------------------if($action=='deletemail'){
Connect();
$id=$_REQUEST['id'];
if($id>0){
46 / 50
$q=mysql_query("DELETE FROM posts WHERE id=$id",$connection);
//if(mysql_affected_rows($connection)>0 ){
if($q<>0){
header('location: design.php?action=5&a=allmail&msg=deleted');
}else{
header('location: design.php?action=5&a=allmail&msg=error');
}
}else{
header('location: design.php?action=5&a=allmail&msg=warning');
}
}?>
Příloha č.4: Style.css
html
{background-color:#000000;}
body
{font-family:arial,sans-serif; font-size: 11px; margin:
0; padding: 0; color: #B0B0B0;}
body,input
{font-family:"Arial CE","Helvetica CE",sans-serif;}
a:link
a:visited
a:hover
{text-decoration:none; font-weight:bold;
{text-decoration:none; font-weight:bold;
{font-weight:bold; color:#ffffff;}
.logoutimage
.imagesy
{border: none;}
{border: none;}
color:#a0a0a0;}
color:#a0a0a0;}
/* Matrjosky */
.matrjoskahlavni
{width: 850px; height: auto; padding: none; margin: 0
auto 0 auto;}
.hlavni
{width: auto; height: auto; padding: none; margin: 0 auto
0 auto; background-color: black;}
.matrjoskainfo
{width: 850px; height:auto; padding: none; margin: 0 auto
0 auto;}
.infologout
{width: auto; height: 24px; padding: none; margin: 0 auto
0 auto; background-color: black;}
.matrjoskamain-up
{width: 850px; height:auto; padding: none; margin: 0 auto
0 auto; float: left;}
.main-up
{width: auto; height: 47px; padding: none; margin: 0 auto
0 auto; background-color: black;}
.matrjoskamain
{width: 850px; height:auto; padding: none; margin: 0 auto
0 auto; float: left;}
.main
{width: auto; height: auto; padding: none; margin: 0 auto
0 auto; background-color: black;}
.matrjoskaobsah
0 auto;}
.obsah
0 auto;}
{width: 759px; height:auto; padding: none; margin: 0 auto
{width: auto; height: auto; padding: none; margin: 0 auto
.matrjoskamain-down
{width: 850px; height:auto; padding: none; margin: 0 auto
0 auto; float:left;}
.main-down
{width: auto; height: 47px; padding: none; margin: 0 auto
0 auto; background-color: black;}
47 / 50
/* Login stuff */
.login
{width: 410px; height:auto; padding: none; margin: 0 auto
0 auto;}
.loginramec
{width: auto; height: 350px; padding: none; backgroundimage: url('img/logo.png'); background-repeat: no-repeat;background-position: top
center; margin: 0 auto 0 auto;}
/*.loginramec
{width: auto; height: 350px; padding: none; backgroundimage: url('img/logo.GIF'); background-repeat: no-repeat;background-position: top
center; margin: 0 auto 0 auto;}*/
.logininner
{width: 300px; height: auto; float: left; margin-top:
220px; text-align:center; position: relative;}
.loginlogin
{width: 300px; height: 37px; margin: 0 auto 0 auto;
padding: none;}
/* Header + info nahore */
.header
{width: 850px; height: 124px; background-image:
url('img/header.jpg'); background-repeat: no-repeat; background-color: black;
;padding: none;}
.info-left
{width: 233px; height: 24px; padding: none; float: left;
background-image: url('img/info-left.jpg'); background-repeat: no-repeat;}
.info-info
{width: 491px; height: 24px; padding: none; float: left;
background-image: url('img/info-info.jpg'); background-repeat: no-repeat; fontweight: bold; color: #89634A;}
.info-logout
{width: 81px; height: 24px; padding: none; float: left;
background-image: url('img/info-logout.jpg'); background-repeat: no-repeat;}
.info-right
{width: 45px; height: 24px; padding: none; float: left;
background-color: black;}
.under-header
{width: 850px; height: 20px; padding: none; float: left;
background-image: url('img/under-header.jpg'); background-repeat: no-repeat;}
.info-jmeno
{width: 50px; height: 24px; float: left; padding: 5px 0 0
0; _padding-top: 0px; margin-left: 85px;}
.info-provincie
{width: 50px; height: 24px; float: left; padding: 5px 0 0
0; _padding-top: 0px; margin-left: 105px;}
.info-rasa
{width: 50px; height: 24px; float: left; padding: 5px 0 0
0; _padding-top: 0px; margin-left: 105px;}
/* Main-up */
.main-up-left
{width: 45px; height: 47px; padding: none; float: left;
background-image: url('img/main-up-left.jpg'); background-repeat: no-repeat;}
.main-up-middle
{width: 759px; height: 47px; padding: none; float: left;
background-image: url('img/main-up.jpg'); background-repeat: no-repeat;}
.main-up-right
{width: 46px; height: 47px; padding: none; float: left;
background-color: black;}
/* Main */
.main-middle
{width: 759px; height: auto; padding: none; float: left;
background-image: url('img/main-back.jpg'); background-repeat: y-repeat; marginleft: 45px; _margin-left: 22px; border: none;}
/* Main-down */
.main-down-left
{width: 45px; height: 47px; padding: none; float: left;
background-color: black;}
.main-down-middle
{width: 759px; height: 47px; padding: none; float: left;
background-image: url('img/main-down.jpg'); background-repeat: no-repeat;}
.main-down-right
{width: 46px; height: 47px; padding: none; float: left;
48 / 50
background-color: black;}
/* Tail */
.tailmenu
both;}
{margin: 0 auto 20px auto; text-align: center; clear:
/* Obsah-left (ikony) */
.obsah-left
{width: 130px; height: auto; float: left;}
.ikony
{width: 98px; height: auto; padding: none; margin-left:
30px; _margin-left: 10px; float:left; font-weight: bold; color: #89634A;}
/* Obsah-main */
.obsah-main
{width: 500px; float: left; background-color: black;}
/* Login page */
.left
{width:27px; height:34px; float:left; background:
url('img/out.png') left top no-repeat; padding: none;}
.leftbut
{width:27px;height:34px;float:left; padding: none;
background-color: black;}
.inputpole
{padding-top:10px;_padding-top:8px; width:100px;
height:34px; float:left; font-size:11px; color: #B0B0B0;border:none;
background:url('img/in.png') 27px top repeat-x;}
.right
{width:27px;height:34px;float:left;font-size:2em;fontweight:bold;color:red;background:url('img/out.png') right top no-repeat; padding:
none;}
.rightbut
{width:27px;height:34px;float:left; font-size:2em; fontweight:bold; color:red; background-color: black; padding: none;}
.buttok
{width:72px;height:27px; font-weight:bold; font-size:
11px; float:left; font-size:11px; color: #896224; border:none;
background:url('img/login-butt.png') no-repeat;}
.buttok2
{width:72px;height:27px; font-weight:bold; font-size:
11px; float:left; font-size:11px; color: #896224; border:none;
background:url('img/registrace-butt.png') no-repeat;}
.underline
{text-decoration:underline;}
.reg_error
{width:376px; height: 245px; text-align: left;
background: url('img/after-registration-war.jpg') left top no-repeat;
color:#000000; padding-top: 95px; padding-left: 35px; /*auto auto 25px;*/ fontweight: bold; margin-top: 35px;}
.reg_ok
{width:376px; height: 245px; text-align: left;
/*background-color:#0f5f0f;*/ background: url('img/after-registration.jpg') left
top no-repeat; color:#000000; padding-top: 95px; padding-left: 35px; /*auto auto
25px;*/ font-weight: bold; margin-top: 35px;}
.div_butt
{width:310px; background-color:#2f2f2f; color:black;
border: 1px solid gray; font-weight: bold; text-align:center;}
.div_butt:hover
{background-color:#4f4f4f;}
/* Tabulka-stavet */
table.stavet
{border-width:2px ;border-spacing:2px; border-style:
solid; border-color: black; border-collapse:collapse; background-color: black;
color: #8093A1;}
table.stavet td
{border: none; padding:4px; border-color: black;}
.stavet_names
{font-weight:bold; color: #8A644B;}
.stavet_top
{font-weight:bold; color: #8A644B;}
.stavet_undertable
{width: 400px; background-color: black; float:left;
padding: none;}
/* Tabulka vypis provincii -> utok */
.utok_vypis
{background-color: #2f2f2f; color: #afafaf;}
49 / 50
.utok_vypis:hover
{background-color: #afafaf; color: #ffffff;}
/* Jednotky v boji */
.my_unit
.enemy_unit
.fight_hr
border: none;}
{color: #10a010; font-weight: bold; }
{color: #a01010; font-weight: bold; }
{color: #232526; background-color: #232526; height: 1px;
/* Buttony a pole */
.selectpole
{width:86px; height:18px; border:2px; bordercolor:#1F2224; border-style:solid; background-color:#1F2224; font-size:11px;
color:#8093A1;}
.selectpole_wa
{width:auto; height:18px; border:2px; bordercolor:#1F2224; border-style:solid; background-color:#1F2224; font-size:11px;
color:#8093A1;}
.numbers
{width:50px; height:16px; padding: none; border: 1px
#1F2224 solid; font-size:11px; color: #B0B0B0; background-color: #1F2224;}
.butt
{width:auto; height:20px; border:2px; bordercolor:#1F2224; border-style:solid; background-color: #1F2224; ;font-size:11px;
font-weight: bold;color:#8093A1; margin-left: 10px; padding: none;}
.txtarea
{width: 300px; height: 80px; border: 1px; border-color:
#646464; border-style: solid; background-color: #E1E1E1; font-size:11px; color:
#646464; margin-top: 10px;}
.hlavnitabulky
.menu
.odkazmenu
.odkazmenu2
{margin: 10px auto 0 auto; width:90%;}
{margin-left: 30px; width: 550px;}
{margin: 0 10px 0 3px;}
{margin: 0 10px 0 10px;}
/* Grafika okolo tabulek */
.okolo
{font-size: 11px; background-color: black; border: none;
padding: 0 0 0 0;}
.up
{width: 100%; height: 15px; background-color: black;
float: left; background-image: url('img/up.gif'); background-repeat: x-repeat;}
.up-left
{width: 15px; height: 15px; background-image:
url('img/tl.jpg'); background-repeat: no-repeat; float: left;}
.up-right
{width: 15px; height: 15px; background-image:
url('img/tr.jpg'); background-repeat: no-repeat; margin: auto 0px auto auto;}
.down
{width: 100%; height: 15px; background-color: black;
float: left; background-image: url('img/down.gif'); background-repeat: x-repeat;}
.down-left
{width: 15px; height: 15px; background-image:
url('img/bl.jpg'); background-repeat: no-repeat; float: left;}
.down-right
{width: 15px; height: 15px; background-image:
url('img/br.jpg'); background-repeat: no-repeat; margin: auto 0px auto auto;}
.lefttable
{background-color: black ; padding: none; width: 15px;
background-image: url('img/left.gif'); background-repeat: y-repeat; backgroundposition: left top; border: none;}
.righttable
{background-color: black ; padding: none; width: 15px;
background-image: url('img/right.gif'); background-repeat: y-repeat; backgroundposition: right top; border: none;}
50 / 50

Podobné dokumenty

manuál redakčního systému

manuál redakčního systému „aA“. Objeví se nám formulář s informacemi o prvním článku. Zde tlačítko stiskneme tlačítko „Editovat text v HTML editoru“ a v okně editoru napíšeme nějaký delší text. Můžeme k formátování textu po...

Více

Emerald Management 200

Emerald Management 200 Qualitative Research in Organizations and Management: An International Journal

Více

MU TÝM WIKIPEDIE - Spolek absolventů a přátel MU

MU TÝM WIKIPEDIE - Spolek absolventů a přátel MU stats.grok.se/cs/201310/Mikuláš Bek …nepozvání rektora MU na hrad v roce 2013 přitáhlo čtenáře…

Více