HRA

Mc Rat
Herní styl Platformer (Single Screen)
Multiplayer Bez multiplayeru
Rok vydání 1998
Programátor Michael Svendsen
Grafik (Unknown)

INTRO

Basic Text Game Engine v2.0 - Kompletní Návod + code manuál

Basic Text Game Engine v2.0 je prostředí vytvořené v jazyce Basic v2.0 pro tvorbu a hraní textových her.

Program jsem napsal při psaní kurzů programování v Basicu na počítač Commodore 64 jako odpověď na časté výtky jedinců, kteří poukazovali na omezení zvoleného typu Basicu na tomto počítači.

Pravda.

Basic v2.0 nemůže být brán jako vrcholné dílo společnosti Microsoft, protože podmínky vzniku, historie obchodních vztahů mezi společnostmi Commodore Business Machines a Microsoft byly v dřevních dobách asi hodně zajímavé. Zvláště, když pan Tramiel, vlastník společnosti Commodore koupil jednorázová práva na použití tohoto basicu do C64.
Na dodělání, či změnu basicu již nebyl asi čas a peníze.



Program pro editaci basicu


Pro tvorbu jsem použil program CBM Studio, které obsahuje kromě editoru assembleru, spritů či znaků velmi slušný editor Basicu s barevným zvýrazněním, možností komprese basicu (odstranění nepotřebných znaků), ale hlavně s možností editovat řádky delší než 80 znaků!
Ano. Commodore64 má totiž jednu nehezkou vlastnost a to schopnost editovat pouze dva řádky textu. Je to omezení prostředí, ne basicu. CBM studio dokáže zapsat řádky basicu o délce 256 znaků, s kterým si interpreter Basicu na C64 hravě poradí.
"Nevýhodou" je nemožnost editovat tyto řádky na standartním C64, právě pro omezení editace maximálně dvou řádků textu. Toto omezení lze také nazvat "ochranou" před nežádoucími změnami kódu.

CBM Studio stahujte zde


1. Engine v kostce


I přes drakonické omezení basicu a minimálního množství použitelných příkazů jsem se rozhodl vytvořit program pro tvorbu co nejkomplexnejší prostředí za pomocí co nejjednoduššího zadávání (čti. editace) textu bez nutnosti programovat jediný řádek!
Nastavení základních pravidel hry se provádí změnou proměnných na vždy uvedeném řádku ( číslo řádku uvádím v závorce ).
Místnost a její vlastnosti se zadávají na pár řádcích pomocí proměnných. Každá místnost má svoji strukturu, kde jsou některé z parametru nepovinné a nemusí se zapisovat.

A na co se můžeme připravit ?

  • Tři základní vlastnosti : Energie, Obrana a Kouzla, která můžeme jen tak dostávat průchodem místností, ale také nám mohou být s každým krokem ubírány.
  • Batoh (inventář) s možností nastavit omezený počet nesených věcí. Každá věc může mít nastavenu energii, obranu a kouzlo, které se při sbírání přičítá k vašim schopnostem.
  • Prohledávání místností, sbírání předmětů a možnost pokládání předmětů v libovolné místnosti. Místnosti si předměty pamatují, takže je lze znova najít a zvednout
  • Kontrola předmětů při příchodu do místnosti. V případě, že máte potřebné předměty, vstup do místnosti je povolen a předměty jsou odebrány. V případě, že nemáte požadované předměty, příběh se odvíjí po alternativní ose.
  • Libovolné množství klávesových zkratek pro větvení příběhu.
  • Boje s nepřáteli. Nepřátelé se jmenují, mají nastavenu energii, obranu a kouzla stejně jako vy a v případě výhry nebo prohry se příběh větví na dva směry.
  • Hrací kostka rozhodující podle hozeného čísla o dalším postupu.

2. Nastavení základních vlastností hry


Proměnná DL (2840) určuje počet existujících předmětů ve hře. DL je nunté pro nadefinování polí, ve kterých se drží nejen jména předmětů, ale i jejich vlastnosti. Proměnnou MX nastavujeme maximální počet nesených předmětů. Vezmeme-li předmětů více, hra nabídne položení předmětů do mísnosti.
Proměnná PG (2840) určuje maximální počet místností. Je potřeba nastavit pro nadefinování polí detailů místností.
V proměnné Z (2840) se uchovává číslo právě navštívené místnosti. Nastavením Z určujete počáteční místnost.
Proměnné PW (energie), DW (obrana) a KW (kouzla) určují začáteční nastavení hráčových schopností. Proměnná PM určuje množství energie, která se má každým krokem odečíst.
Proměnnou XT určujeme, zda-li se předměty v nové místnosti nabídnout ihned ke zvednutí (XT=1) nebo musíme místnost prohledat ručně stiskem klávesy "1" (XT=0).
V proměnné typu string NM$ zadáme název hry.
Proměnná BD$ určuje počáteční obsah batohu. Existující předmět je zde definován znakem "+", ostatní znakem ".". Nastavení pak může vypadat následovně : BD$ = "++......+.". V tomto případě má hráč po startu první, druhý a předposlední předmět z existujícího seznamu předmětů.
V proměnné QY$ a QN$ se drží klávesová zkratka pro odpověď ANO a NE.
Proměnná NI$ obsahuje větu, která se zobrazuje hráči pokud v místnosti hledá marně. Pro vlastní šetření paměti je určena stringová proměnná SL$(index), která slouží k uchování často se opakujících se slovních výrazů.


3. Nastavení obsahu batohu


Základním prvkem textových her či adventur je batoh plný věcí potřebných k plnění úkolů. I my máme možnost mít batoh. Počet možných věcí v batohu se nastavuje proměnnou DL (2840).
Počet prvků v batohu není omezený a definice probíhá v několika proměnných. Ve string B$(index) je uchován název položky. S odpovídajícím indexem v proměnné B se ve víceúrovňovém poli nastavují jednotlivé vlastnosti prvků batohu. (3120 - 3235). Nastavení vlastností je následoovné : B(index, energie), B(index, obrana) a síla kouzla B(index, kouzlo).

Počtu možných prvků batohu musí odpovídat počet znaků v proměnné BD$ (2880) a v definicích jednotlivých místností při testování, proměnná T$ (3530) či přidávání a ubírání předmětů, proměnná BX$ (3480).

Příklad.

Počet položek v inventáři je nastaven na 10 zápisem DL=10
Proměnná BD$ nebo BX$ v nastavení místostí je zapsána z deseti znaku : BD$="++......--"

Znaky v zápisu batohu :

  • + (plus) - Přidávání předmětu na odpovídající pozici (proměnná BX$) nebo testuje existenci položky . (proměnná T$)
  • - (minus) - Odebírání předmětu na odpovídající pozici. U testování při vstupu do místnosti se nepoužívá.
  • . (tečka) - Tečka je jen doplňující znak a odpovídá předmětu na pozici.

Příklad použití při pěti položkách, které může batoh obsahovat:

    BD$ = "++..." : Nastavení batohu, v kterém je po startu první a druhý předmět.
BX$(10) = "...+-" : V místnosti 10 obdržíte předposlední předmět a o poslední přijdete.
  T$(5) = "+..+." : V páté místnosti se testuje zdali máte první a předposlední předmět.

4. Vytváření místností


Vytváření místností a logiky celé hry je zcela jednoduché. Každá místnost je definována pár řádky, které obsahují povinné a volitelné proměnné. Všechny proměnné patřící jedné místnosti musí mít v indexu stejné číslo místnosti. V případě delších textů definované proměnnou P$ se jedná o vícerozměrné pole definované číslem místnosti a indexem od 0 do 5.


5. Přehled proměnných pro vytváření místností


N$(místnost) Textový nadpis místnosti
P$(místnost,index) Dlouhé popisy lze zapisovat do vícerozměrného pole pomocí indexu 0,1,2 ... např:
P$(místnost,0) "První dlouhý text popisku místnosti."
P$(místnost,1) "Druhý dlouhý text popisku místnosti."
P$(místnost,2) "Třetí dlouhý text popisku místnosti."
BX$(místnost) = "++...-..-." Obsah batohu, kde znakem "+" předmět v místnosti získáme, znak "-" předmět odebere. Znak "." je neutrální a odpovídá položce v batohu
T$(místnost)="++...-..-.": T(místnost) = 20 Testuje obsah batohu BD$ s nastavením proměnné T$. Pokud máte potřebné předměty, místnost se zobrazí. Pokud ne, jste přesměrování na alternativní místnost uvedenou v proměnné T
K$(místnost) Zadávání volby klávesnicí nebo kostkou, výši energie a pod.
K$(místnost)="k/a002" První znak "k" znamená kávesnici a po stisku klávesy "a" pokračujeme do místnosti 2
K$(místnost)="k/r021/h056" První znak "k" znamená kávesnici a po stisku klávesy "r" jdeme do místnosti 21 a stiskem klávesy "h" se přeneseme do místnosti 56. Podmínek na stisk klávesy může být libovolné množství.
K$(místnost)="d/a002/b043/c005/d006/e005/f056" První znak "d" znamená zobrazení kostky a po zastavení kostky klávesou "space" hodnota hodu odpovídá písmenu v nastavení. Tzn. Při hodu čísla 1(a) jdeme do místnosti 2, při hodu hodnoty 2(b) místnost 43 atd...
Čísla místností musí být uvedena v trojpísmené délce.
K$(místnost)="e" Skok na místnost, která odpovídá hodnotě počtu získané energie. Opatrně ať se nedostanete mimo maximální hodnotu místností indexu pole proměnné "Z".
K$(místnost)="r" Reset hry a skok na začátek programu. Používá se u poslední místnosti ve hře.
BB$(místnost)="+010/+002/-003" Přidávání / Ubírání energie, obrany a kouzel. Tento příklad přidá 10 jednotek energie, přidá 2 jednotky obrany a ubere 3 jednotky kouzel
FL(místnost)=1: FJ$(místnost)="obr zlobr": FX(místnost,0)=10: FX(místnost,1)=3: FX(místnost,2)=0: FP(místnost)=3 Nastavení nepřítele, kde proměnná FL zna, zda-li je nepřítel živý(1) nebo mrtvý(0). FJ obsahuje název zloducha. FX obsahuje nastavení energie(0), obrany(1) a kouzla(2) nepřítele a proměnná FP odkazuje na stránku v případě hráčovy prohry.

A to je vlastně vše, co je potřebné k vytvoření kompletní a komplexní hry reagující nejen na náhodu, ale i na schopnosti řešit hádanky a správně se rozhodovat.
V další kapitole si ukážeme vytvořenou minihru o pěti místnostech, kde jsou použity takřka všechny herní mechanismy.


6. Vytváříme a hrajeme hru


Projdeme si postupně celý příběh textové minihry s rozborem použitých vlastností.
Začínáme nastavením jména hráče a zadáním oslovení hráče.

Při editaci místností lze oslovení použít i v textu jednotlivých místnosti zápisem:

P$(10,0) = "Ahoj "+JM$+", jak se mas ?"

Respektive jakoukoliv proměnnou, která je použita ve hře lze použít i v textech nebo nadpisech místností.


Logo Unreal je vytvořeno příkazem PRINT, který dovoluje za uvozovky zapsat kódy nejen funkčních kláves ale i barev. Díky tomu můžete kreslit a pohybovat se do všech stran, stejně jako by jste hýbali kurzorovými klávesami a mačkali znaky.

S trochou práce lze vytvořit nejen logo, ale například i lehký demoefekt :)

Těchto pár řádků se postará o vykreslení celého loga Unreal včetně barev. Na začátku každého řádku je nastavení pozice na X a Y řádek.
Ti zkoumavější si všimnou, že jsem otočil osu X a Y :) a z lenosti to tam již nechal ...


Začátek hry, místnost č.0


Zde již začíná příběh, který jsme nadefinovali pomoci proměnných.

Nadpis je jasně definovaný v proměnné N$ (3450) a text místnosti v polích P$(0,0). Automaticky jsme při vstupu obdrželi energii a obranu z proměnné : zápis BB$(0) = "+010/+002/+000"
Po obdržení se hodnoty vlastností mažou a pokud bychom znova prošli touto místností, znova je již neobdržíme.

Protože jsme nastavili proměnnou XT=0 (2840) tak, aby neukazovala předměty po navštívení místnosti, předměty jsou v proměnné místnosti BX$(0) = "++.+...+...." sice nastaveny, ale čekají na objevení stiskem klávesy "1".
Po stisku klávesy "1" se místnost prohledá a nalezené předměty zobrazí.
Stiskem klávesy "A" předměty vezmeme, klávesou "N" nabídku odmítneme. Klávesy se nastavují v proměnných QY$="a": QN$="n" (2890)

Po stisku klávesy "A" jsme předměty sebrali, ale jelikož máme v batohu více předmětů než nám dovoluje proměnná MX=3 (2840), hra nám okamžitě nabídne obrazovku, kde nás nutí upustit nějaký ze sebraných předmětů. Každému předmětu v batohu odpovídá písmeno, kde stiskem odpovídajícího písmene položíme položku zpět do místnosti.
Stiskem klávesy "B" jsme tedy položili sirky zpět do místnosti.

Engine si pamatuje, kde byly položky ponechány a v příštím průchodu můžete sirky opět nalézt.

Místnost jsme znova prohledali stiskem klávesy "1", ale předmět již nezvedli.
Místnost má nastaveno následujícím zápisem, aby čekala na stisk klávesnice a čeká na stisk klávesy "P", která nás přenese do místnosti 1.

3500 K$(0)="k/p001"

1. místnost - test na předměty


Při vstupu do místnosti č.1 se testuje zápisem...

3530 T$(1) = "++.........."
... zda-li máme pořebné předměty, které nám umožní vstup do místnosti. Proměnná se testuje s obsahem batohu BD$ a pokud předměty nemáme, zobrazí se seznam chybějících předmětů.

V případě, že předměty nemáme, příběh pokračuje tam, kam ukazuje proměnná T

3540 T(1)=0
V našem případě nás proměnná T posílá opět na začátek, kde sebereme sirky a upustíme například tužku.
A jelikož jsme to provedli, při opětovném stisku klávesy "P" v první místnosti nás hra pustí dále.


Boj s nepřítelem


Nastavení následující místnosti má za následek okamžitý boj s nepřítelem definovaným na řádku 3590. Proměnná FL (3590) znamená, že je živý, jmenuje se Kraken a má sílu 17, obranu 4 a kouzlo 0.
V proměnné FP (3590) se nachází číslo místnosti v případě hráčovy prohry. V případě výhry se zobrazí text místnosti.

3590 FL(2)=1:FJ$(2)="Kraken":FX(2,0)=17:FX(2,1)=4:FX(2,2)=0: FP(2)=1

Začátek boje je průběhem matematických operací, který má pravidla do kterých zasahuje náhoda. Celková síla hráče a nepřítele se počítá z následujících výpočtů :

1240 s1=pw+(dw*2)+(kw*4)
1250 s2=FX(z,0)+(FX(z,1)*2)+(FX(z,2)*4)
Z ukázky lze vidět, že energie hráče (PW) i nepřátelova energie FX(z,0) se sčítá s obranou, která se násobí dvěma a kouzlem, které se násobí čtyřma. Tím vzniká počáteční celková síla obou hráčů.

Celý proces souboje je jednoduchý a vychází z generování náhodných hodnot v určitém rozssahu, kdy se hodnota náhody přičítá k energii jak hráče, tak nepřítele.

1260 na=int(rnd(1)*10): nb=int(rnd(1)*10):PR=PR-1
1270 s1=s1+na: s2=s2+nb

Tento jednoduchý matematický výpočet se provádí v určitém počtu opakování, které se generuje opět náhodně. A protože generování náhody na Commodore 64 není zase tak náhodné, jak by se mohlo zdát, musíme náhodě pomoci generátorem času, který má Basic v2.0 schovaný v proměnné TI$ nebo T. Nastavení počtu průběhů souboje se děje na řádcích

1230 pr = val(mid$(ti$,5,2))
1231 if pr<30 then pr=pr+60

Basic v2.0 má totiž v proměnné TI$ právě běžící čas od posledního restartu ve formátu hodin "HHMMSS". My na řádku 1230 bereme počet aktuálně probíhajících sekund a pokud je toto číslo nižší než 30 (řádek 1231), přičteme k počtu průběhů hodnotu 60.
Tímto "hackem" se určuje počet průběhů souboje s nepřítelem.

V případě, že se souboj vyvíjí lépe pro hráče, je rám obrazovky černý. V případě nadvlády nepřítele je rám obrazovky červený.
Hodnoty souboje se neustále zobrazují na obrazovce.

Pokud hráč prohrál, zobrazí se informace a příbeh se odehrává tam, kam ukazuje proměnná T.
V našem případě nás hra vrátí zpět na místnost před bojem s Krakenem.

Po opětovném pokusu o boj s Krakenem přeci jen hráč vyhrál.

Při výhře se zobrazí text místnosti ...

... a prohledáme-li tuto místnost, najdeme zde i mrtvého Krakena.
Klávesou "space" pokračujeme dále.


Hážeme kostkou a recyklujeme


Protože paměť začne s přibývajícím příbehem rychle ubývat a v některých případech je nezbytné psát u více místností stejný text, proměnou
PA (3640) můžeme nastavit, z které místnosti máme tento text načítat.

Stejný text například potřebujeme tam, kde prohledáváme jednu místnost několikrát za sebou, ale větvení příbehu potřebujeme pokaždé měnit. V našem případě sice zobrazujeme text z místnosti 1

3640 PA(4)= 1
Narozdíl od první místnosti, kde se rozhodovalo stiskem klávesy se zde rozhoduje za pomocí kostky.

O to, že se bude házet kostkou se stará zápis na řádku 3650 a první znak v řetězci, znak "D".

3650 K$(4)="d/a003/b003/c003/d003/e003/f003"

Zápis jasně ukazuje, že všechny volby, které mohou padnou odkazují na stránku "3". Klávesou "space" kostku zastavíme a podle zastaveného čísla nás engine pošle na patřičnou stránku.


Více podmínek


Takřka vždy je potřeba se rozhodovat podle více možností volbou klávesnice. Tato místnost nám dovoluje stisknout jednu ze čtyř kláves a ...

... podle stisknuté klávesy nás hra pošle do ...

Konce :)


Konec ?


Ukázka v tomto návodu je skutečná minihra o pěti obrazovkách a ukazuje drtivou většinu možností Basic Text Game Engine.
Jednoduchost spočívá v pouhém přidávání jednotlivých místností a provazováním příběhu na základě všemožných podmínek, náhod soubojů a v neposlední řadě předmětů, které můžete na své cestě sbírat.
Jelikož je paměti málo a při zapisování začne velmi rychle ubývat, rozšiřování tohoto zcela funkčního enginu o mnoho dalších funkcí je jen na úkor možného počtu místností, které jsou tak potřeba.
( mimochodem já se dostal na omezení počtu 87 místností a pak už to Basic prostě nebral :)
Při psaní příběhu vám bude největší přítel tužka a papír a pokud budeme mít chuť, můžete tento program použít na to, aby jste si nakonec vaši hru zahráli.
Celý zdrojový kód pro CBM studio včetně ukázkové minihry si můžete stáhnout zde.
Samotná minihra ve formátu PRG je ke stažení zde.

Petr Chlud alias PCH / Unreal


ps. Aktualizace z verze 1.1 na 2.0 proběhla zcela spontálně poté, co jsem po napsání manuálu k verzi 1 zjistil, jak je škaredá :)

Nový příspěvek k článku

podpis :
První znak podpisu musí být vykřičník, jinak se příspěvek neodešle (ochrana proti spamu)

24.08.2019 - PCH

Ano. Já se to dozvěděl až včera při sledování videa o Simons Basicu na youtube :) Tak jsem udělal jsem takový malý paměťový benchmark a zadání bylo následující:
Proměnné ve hře, které nemusí být float převést na int a paměťové výsledky byly následující ( jedná se hlavně o dimenzování polí a jejich indexy ):

Po spuštění hry volná paměť bez úprav : 18 889 Bytes free
Převod T na T% = 19 077 Bytes free
Převod FX na FX% = 19 843 Bytes free
Převod FP na FP% = 20 103 Bytes free
Převod FC na FC% = 20 306 Bytes free
Převod B na B% = 20 445 Bytes free

Zde je vidět, že rodíl je opravdu nezanedbatelný.

Dále jsem vytvořil jednoduchý prográmek pro výpis paměti před a po dimenzování polí a ve zkratce :

Pomocí FLOAT

10 DEF FN FR(X)=FRE(0)-65536*(FRE(0)<0)
20 PRINT FN FR(0)
30 DIM A(2000)
40 PRINT FN FR(0)

před dimenzováním : 38 817 bytes free
po dimenzování : 28 805 bytes free

A pomocí INT

10 DEF FN FR(X)=FRE(0)-65536*(FRE(0)<0)
20 PRINT FN FR(0)
30 DIM A%(2000)
40 PRINT FN FR(0)

před dimenzováním : 38 817 bytes free
po dimenzování : 34 807 bytes free

Z toho lze dopočítat, že :
dimenzujete-li pomocí FLOAT čísla (A), délka jednoho pole je 5 bytů
dimenzujete-li pomocí INT čísla (A%), délka jednoho pole jsou 2 byty.

A v dalších příspěvcích přidám něco o "komickém" basicu ... resp. o "vychytávkách"

23.08.2019 - jirka

Tak to jsem netušil, že ten pro mne dosud "skoro-basic" rozlišuje číselné proměnné a má možnost určit integer. To se musím tomu basicu nejen v duchu omluvit. Tohle na Atárku neumí ani TBasicXL - tedy výrazně vylepšená verze Basicu, která se musela nejprve načíst (natož ten vestavěný).

Takže 2x palec hore:
1. za udělátor textovek samotný
2. za pro mne zásadní info o vychytávce s integerem v pro mne dosud komickém Basicu

23.08.2019 - PCH

Ještě jedna věc, kterou jsem zjistil a to ta, že kde není potřeba používat FLOAT k deklaraci počtu prvku polí .. resp .. kdo by potřeboval FLOAT k indexování polí :) tak se prostou změnou zápisu z původního:

DIM A(100)

na

DIM A%(100)

ušetří kotel paměti .. čti bytů. Zjevně si Basic alokuje pro proměnné typu INT (%) méně prostoru v paměti. U prosté změny deklarace u ukázky ke stažení je rozdíl 2000 bytů !!!! a to je kotel místa.

23.08.2019 - PCH

V teto verzi probiha souboj do prubehu=10. V dalsi verzi je jiz opraveno ...

Advert

Hardcode and datamining by PCH of UNREAL, Hardware guru by RAY of UNREAL, Bugs report by SILLICON of UNREAL
UNREAL 2014-2021 Czech republic