Konfiguracja testów TDD w projekcie JS z pakietami Mocha i Babel.

Konfiguracja narzędzi do budowania projektów w JavaScript bywa czasem czarną magią. Zmuszenie do współpracy różnych frameworków zajmuje dużo czasu, ale efekt konfiguracji służy nam potem długo. Dzieląc się poniżej swoim wysiłkiem może zaoszczędzę go komuś innemu.

W tym poście opiszę konfigurację narzędzi BabelMocha/Chai do zbudowania i wykonania testów typu BDD/TDD w przeglądarkowym projekcie JavaScript. Moje testy jednak dotyczą konkretnych klas i funkcji JS, a nie zachowania się UI, ponieważ projekt, w którym je stosowałem był grą rysowaną na canvasie.
Opiszę również mój konkretny use case, bo zdaję sobie sprawę, że konfiguracja nie musi być uniwersalna. Będę również wtrącał uwagi dla kompletnie początkujących w świecie narzędzi JS, w którym sam na początku nieźle się gubiłem.

Mój use case:

Chciałem utworzyć testy jednostkowe przy pomocy Mocha/Chai.
Mój kod JS to klasy umieszczone oddzielnie każda w swoim pliku z export default NazwaKlasy; na końcu. Pliki są zebrane i wyeksportowane osobno w jednym pliku index.js, tak aby można było importować potrzebne klasy w innych plikach z jednego pliku.
To tworzy pewne drzewo zależności, które może być dość pokaźne. Jednakże w danym teście interesuje nas testowanie konkretnej metody z konkretnej klasy – jej zależności powinny być dla twórcy testu przezroczyste. Niestety wtedy (luty 2020), o ile importy były zgodnie z moimi oczekiwaniami interpretowane przez przeglądarki, o tyle moduły Node, którymi są Mocha i Chai, rządziły się swoimi prawami. Z kolei ja, wracając do JS po 15 latach przerwy, nie orientowałem się w zawiłościach standardów ES, ich historii czy pokryciu przez przeglądarki i Node.js. Próbując wykonać testy bezpośrednio z Mocha/Chai otrzymywałem komunikat:

import { math, AnotherClass, MyOtherClass } from '../index.js'
^^^^^^
SyntaxError: Cannot use import statement outside a module

Przykładowy plik Market.js z definicją testowanej klasy Market wygląda tak:

import { math, AnotherClass, MyOtherClass } from '../index.js'
class Market {
  constructor () {
    // code here
  }
  methodToTest(input) {
    let output = 0
    if (input <= 10) 
output = -2
    else if (input <= 40) output = -1
    return output
  }
}
export default Market

I chciałem żeby plik market-test.js z testami wyglądał tak:

var assert = require('assert')
import { Market } from '../index.js'

describe('Market', function() {
    var market = new Market()
    describe('#methodToTest()', function() {
        it('should return 0 if input is greater than 40', function() {
           assert.equal(market.methodToTest(45), 0)
        })
    })
})

Moje rozwiązanie:

Pierwsze co przyszło mi do głowy to użycie webpacka (narzędzia do budowania aplikacji JS-owych), którego już używałem do budowania aplikacji na produkcję. Okazało się, że można to zrobić prościej korzystając tylko z npm, którego i tak się wykorzystuje do konfiguracji i instalowania zależności w projekcie, Babela, który załatwia nam kompilowanie JavaScriptu na odpowiednią wersję oraz samego tandemu Mocha – Chai do testowania. Zaletą tego rozwiązania było też zmniejszenie liczby plików konfiguracyjnych do dwóch i brak tworzenia plików tymczasowych.

Co zatem należy po kolei zrobić:

  1. Instalacja MochaChai za pomocą npm:
npm install --save-dev mocha chai

Zakładam, że projekt został zainicjowany w npm i plik package.json istnieje w katalogu głównym projektu.

  1. Instalacja niezbędnych pakietów Babel:
npm install --save-dev @babel/core @babel/plugin-proposal-class-properties @babel/preset-env @babel/register babel-plugin-transform-remove-console
  1. Stworzenie w pliku package.json wpisu ze zmiennymi środowiskowymi Babel:
"babel": { 
    "env": { 
        "test-console": {
            "presets": [ "@babel/preset-env" ],
            "plugins": [ "@babel/plugin-proposal-class-properties" ] 
        }, 
        "test": { 
            "presets": [ "@babel/preset-env" ], 
            "plugins": [ "@babel/plugin-proposal-class-properties", 
                         "transform-remove-console" 
                       ] 
        } 
    } 
},

Wpisu dokonuje się na pierwszym poziomie drzewa JSON.
Te dwa ustawienia środowisk różnią się tym, że w drugim przypadku usuwane są wszelkie zapisy console.log czyniąc wynik testów czytelniejszym. Jest to pewnie dla wielu domyślny sposób ich uruchomienia. Drugie ustawienie (test-console) będzie pozwalało na zobaczenie wszystkich zrzutów, których dokonują testowane metody.

  1. Stworzenie w pliku package.json wpisów pozwalających uruchomić za pomocą npm testy z różnymi ustawieniami:
"scripts": { 
    "test": "BABEL_ENV=test mocha || TRUE", 
    "test-watch": "BABEL_ENV=test mocha --watch || TRUE", 
    "test-console": "BABEL_ENV=test-console mocha || TRUE"
}

|| TRUE pozwala ominąć nic niemówiące błędy npm. Jeśli jakieś błędy pakietów się pojawią, to i tak będą najczęściej widoczne od razu w terminalu.
test-watch pozwala na śledzenie zmian w plikach i automatyczne odpalanie testu po zapisaniu pliku źródłowego.

  1. I na koniec skonfigurowanie frameworku mocha z biblioteką chai w pliku .mocharc.js (koniecznie uwaga na kropkę na początku nazwy pliku) w katalogu głównym projektu:
module.exports = { 
    require: ['chai', '@babel/register'],
    ui: 'bdd', 
    reporter: 'spec',
    growl: false,
};

Domyślnie mocha zakłada, że pliki z testami są w katalogu test

  1. Na koniec nie pozostaje nic innego jak uruchomić npm run test i cieszyć się takim wynikiem:
> BABEL_ENV=test mocha || TRUE

  Market
    #methodToTest()
      ✓ should return 0 if input is greater than 40 

  1 passing (4ms)

W razie potrzeby dodatkowych konfiguracji zachęcam do odwiedzenia stron:
npmhttps://docs.npmjs.com
babelhttps://babeljs.io/setup
mochahttps://mochajs.org
chaihttps://www.chaijs.com

Jeśli będą pytania, z chęcią odpowiem na nie w komentarzach.

Miłych testów!
Tomek.

B2B #1 – W co gram i po co?

Cześć Świecie! Ponownie.

Chcąc wrócić do blogowania, wymyśliłem serię szybko, acz zręcznie pisanych blogów o nazwie B2B – Back to blogging (powrót do blogowania). Powinny zająć mi mniej czasu i zachęcić do regularniejszego blogowania. Po samym blogu sądząc może się wydawać, że nic się u mnie nie dzieje, tymczasem jest to zupełnie mylne wrażenie 🙂

Zaczynając od czegoś zupełnie lekkiego. Zorientowałem się, że tworząc moją kolejną grę lub myśląc o następnej potrzebuję swobodnego dostępu do inspiracji i pomysłów na mechaniki, z których mogę wybierać jak ze sklepu. Chciałbym, żeby to był różnorodny zestaw,  a patrząc na historię mojego grania  w gry komputerowe – ponad 1300h w Dota 2 o tej różnorodności może nie świadczyć. Stąd ostatnio, gdy poświęcam swój czas staram się poznawać szersze spektrum gier ze swojej przepastnej biblioteki, by zwiększyć swoją grową erudycję.

Poniżej chciałbym przedstawić kilka gier, w które aktualnie gram, jakie mam wrażenia z gry, dlaczego po nie sięgnąłem, co mi przyszło do głowy od strony game designu po rozgrywce.

1. The Bureau: XCOM Declassified

W tę grę grałem już pięć lat temu, ale musiałem zacząć od początku ponieważ kompletnie nie pamiętałem, jak się nią steruje. Przy okazji zaserwowałem sobie poziom trudności Veteran – o jeden wyżej niż najprostszy Squaddie, co kompletnie zmieniło mój obraz gry.

Jest to taktyczna strzelanka trzecioosobowa. Widok jest z trzeciej osoby i kierujemy trzema osobami naraz, taki dwupak 😉
Rzecz dzieje się w latach 60-tych, w trakcie inwazji obcych na Ziemię. Fabuła inspirowana jest pomysłami z oryginalnych gier UFO: Enemy Unknown i X-COM. Ponieważ jednak większość z tych gier jest strategiami turowymi z elementami ekonomicznymi, bardzo podoba mi się, że mogę brać udział w tym świecie z nowego innego punktu widzenia, niezależnie jak bardzo lubię ten klasyczny model rozgrywki w X-COM. Jest tu dużo nawiązań do serii X-COM – wygląd niektórych obcych, centralna, tajna baza ds. UFO, czyli właśnie ten X-Com, zdobywanie technologii obcych, customizowanie i rozwój postaci, które wraz z doświadczeniem bojowym stają się odporniejsze i zdobywają nowe umiejętności. Ten element wraz z podwyższonym poziomem trudności sprawił, że po nadaniu swojskich, polskich nazwisk moim agentom, nieraz restartowałem misję, nie mogąc pogodzić się ze stratą agenta. Dodatkowo, mimo, że można rekrutować nowych agentów, to starzy są wyjątkowo cenni, bo żółtodzioby zaczynają zawsze od pierwszego poziomu doświadczenia.

System wydawania poleceń i osłon podobno jest skopiowany z Mass Effect, nie wiem, nie grałem jeszcze, ale jeśli tak, to dobrze, bo jest dobry i ciekawy. Wyzwaniem jest wydawanie poleceń swoim dwóm towarzyszom – gdzie mają podbiec, jakiej umiejętności użyć, do którego ufoka strzelać, z równoczesnym strzelaniem i eliminowaniem ufoków swoim własnym agentem (dowódcą). Na szczęście wydawanie poleceń jest w tak zwanym Battle Focus Mode, który charakteryzuje się mocno zwolnionym tempem rozgrywki oraz efektem 'rentgena’, dzięki którym widzimy rozmieszczenie obcych. W tej grze taktyka, rozmieszczenie agentów, flankowanie, wspólne używanie umiejętności, aby dorwać różne rodzaje ufoków ma tak samo duże znaczenie jak refleks, spokój i celne strzelanie.

2. Hard West

W związku z premierą Phantom Doctrine, postanowiłem odświeżyć sobie i pójść dalej w rozgrywce w poprzedniej grze polskiego studia Creative Forge Games o nazwie Hard West.
Jest to turowa strategia, wzorowana na systemie rozgrywki wyżej wspomnianej serii X-COM, ale osadzona w mrocznym i lekko diabolicznym świecie Dzikiego/Dziwnego Zachodu. Ponieważ jestem fanem X-COM i tego typu rozgrywki, bardzo się cieszyłem na taką grę w nowym uniwersum.

Gra ma dość rozbudowaną wartwę fabularną, głównie przedstawianą na trójwymiarowej mapie, po której chodzimy znacznikiem drużyny i odwiedzając różne lokacje czytamy teksty i dokonujemy różnych wyborów poznając i pchając narrację do przodu. Ostatecznie narracja zawsze prowadzi do jakiegoś konfliktu, który rozgrywamy turowo w świetnie wykonanych lokacjach Dzikiego Zachodu. Fabuła jest ciekawie napisana, a kolejne scenariusze nawiązują do poprzednich stawiając nas często po drugiej stronie konfliktu, co uważam za bardzo ożywczy pomysł. Niemniej czasem chodzenie po mapie i czytanie kolejnych tekstów wydaje się przydługie, gdyż cały czas chce się jak najszybciej przejść do kolejnej potyczki i strzelaniny – tak fajnie jest zrealizowana.

Z ciekawych rozwiązań nie wprost X-COM-owych, to system szczęścia, który powoduje, że czasem można uniknąć nawet pewnego strzału, co trochę eliminuje zagrożenie, że kto strzeli pierwszy wygrywa. Szczęście się wyczerpuje, trzeba o nie dbać, co daje dodatkową oś taktyczną. Fajny jest system kart, które są kartami do pokera przypisywanymi do poszczególnych postaci. Zdobywamy je w trakcie scenariusza i dają one dodatkowe umiejętności postaciom, można je przed bitwą między postaciami wymieniać, a także jeśli dany bohater ma w zasobniku jakiś układ z pokera dostaje dodatnie modyfikatory do cech, im lepszy układ kart tym lepsze modyfikatory.
Moje ulubione umiejętności, to golden bullet – trafia na miejscu każdego wroga, przechodząc w prostej lini przez wszystkie przeszkody oraz ricochet – nie tak śmiercionośny, ale satysfakcjonujący system strzelania posługując się różnymi metalowymi przedmiotami postawionymi na planszy – jak wiadro czy hydrant, dzięki którym można trafić przeciwnika ustawionego dobrze za zasłoną.

3. Gwint i Wojna Krwi: Wiedźmińskie Opowieści

W te dwie gry gram na GOG.COM w sumie na przemian, są ze sobą dość związane, ponieważ opierają się na systemie karcianki, który można było spotkać w grze Wiedźmin 3. Został on później rozwinięty i usamodzielniony w odrębnej grze karcianej jaką jest Gwint. Gwint jest sieciową grą wieloosobową, w której toczymy karciane potyczki, a Wojna Krwi, to takie jej fabularne dopełnienie. Zresztą w samym Gwincie mamy przycisk, który nas do Wojny Krwi przełączy jeśli mamy ją zainstalowaną.

Wojna Krwi jest reklamowana jako nowy RPG w świecie Wiedźmina i jest to dość mylące. Kupiłem ją w ciemno, bazując na reputacji CDP RED i ich poprzednich grach i moje wyobrażenia, dotyczącego tego czym jest ta gra były trochę inne. Niemniej po pierwszym zdziwieniu wciągnąłem się w tą opowieść o królowej Meve dzielnie walczącej z inwazją Nilfgaardu. Opowieść wiedzie nas przez wsie, łąki i miasteczka, gdzie królowa wraz ze swoją armią odkrywa różne intrygi, bandytów, armie najeźdźców i rozwiązuje te problemy podejmując ważkie w konsekwencjach decyzje lub przez bezpośrednie starcia.
Dodatkowo królowa zbiera zasoby, dba o morale swojej armii, rekrutuje nowych wojaków. A potyczki są rozgrywkami opartymi o Gwinta. Różnią się jednak od nich o tyle, że bardzo często są swoistymi zagadkami logicznymi, w których mamy dostęp tylko do jednej tury gry (a nie 3, jak w Gwincie) podczas której mamy ściśle wyznaczony cel, konkretne karty z talii i niespodziewane karty ze specyficznymi zachowaniami u przeciwnika. Czasem przyjdzie nam też stoczyć regularną 3 turową bitwę. Jest to dość ożywcze i w dużym stopniu eliminuje (przynajmniej na początkowym etapie rozgrywki) ból zarządzania i dobierania kart do talii, szukania kombosów, co mnie trochę męczy w karciankach z dużą ilością różnych kart. Sytuacja, w której przegrywam, bo nie spędziłem 3 godzin na wymyślaniu talii, a nie dlatego, że grałem źle, bywa frustrująca.

4. Spelunky

Odświeżona gra Spelunky w wersji na PC grana koniecznie przy pomocy pada.
Wybitnie frustrująca platformówka, w której bardzo łatwo stracić trzy życia i trzeba zaczynać od początku. Mimo to satysfakcja z ukończenia poziomu albo dwóch gwarantowana dzięki fajnej fizyce postaci i otoczenia, dość urozmaiconych przedmiotów do wykorzystania, systemowi losowo generowanych etapów i zabawnym spotkaniom głęboko wewnątrz lochów.


Polecam obejrzeć powyższy filmik, tam jest szybko wyjaśnione na czym polega doświadczenie tej gry. Mnie z kolei z punktu game designu zainteresowała fizyka postaci i wrogów w tej grze. Sterowanie jest proste, ale postać ma dość duży garnitur ruchów w zaleźności również od otoczenia, w którym jest w interakcji. Dodatkowo mimo, że postać ma duże możliwości pokonywania pomieszczeń, to musi wykonywać to dość precyzyjnie, skoordynowanie w czasie i szybko, ponieważ pułapek jest dość dużo, różnorodnie umieszczonych, a czas na pokonywanie levelu mija nieubłaganie.
Fajne jest to jak gra ma momenty, w których czujesz się usypiająco bezpiecznie, żeby tuż za momencik zwalić się Tobie na głowę. Skakać można z dość dużej wysokości, ale nieraz zdarzyło mi się spaść tak nisko, że grawitacja upomniała się o swoje. Dodatkowe atrakcje można też stworzyć sobie samemu gdy po raz kolejny okaże się, że pomyliło się przyciski i upuściło sobie pod nogi bombę. Trzeba salwować się ucieczką w losowo wyznaczonym kierunku, oczywiście na ogół tuż pod pocisk strzelający z pułapki w ścianie, albo pająka opuszczającego się na nici z sufity, zachęconego naszą nagłą obecnością. W tej grze jest ważny timing – za późno lub za wcześnie odpalony bicz, to na ogół pudło i nietoperz siedzi Ci już na głowie, a nerwowe odpalenie bicza ponownie to strata kolejnego serducha. Animacja bicza trwa tyle i tyle, nietoperka trzeba trafić tuż nad głową, jak nie umrzesz 1000 razy, to nie wyćwiczysz.

Grafika słodka i prosta, pokazuje mi jak prostymi i sympatycznymi sposobami można uatrakcyjnić rozgrywkę. Gdy chcemy wypuścić linę, dajemy gałkę w górę, postać zadziera głowę, a ekran się przesuwa trochę, żebyśmy mogli zobaczyć co jest nad nim. Każdy skok i lądowanie, to wznoszący się kurz spod nóg bohatera, a zabity nietoperz czy pająk, to wielkie krople krwi rozbryzgujące się dookoła.

5. Costume Quest

Gra od Double Fine Tima Schaffera odpowiedzialnego dawno temu (1993) za Day Of The Tentacle, a całkiem 'niedawno’ za Brutal Legend. Co ciekawe miałem kłopot, żeby znaleźć jakąś rozsądną recencję lub gameplay po polsku na YT, stąd krótkie wprowadzenie bez komentarza poniżej.

Do gry powróciłem w związku z ostatnim Halloween, do którego gra nawiązuje, bo właśnie podczas tego dnia toczy się akcja. Wcielamy się w chłopca lub dziewczynkę, którym łasy na cukierki potwór porwał siostrę/brata ponieważ była przebrana za cukierka i tak chodziła od domu do domu, w jednym z nich grasował potwór. Ja wcieliłem się akurat w dziewczynkę, a cel rozgrywki polega na odszukaniu i uratowaniu brata. W tym celu będziemy musieli przeszukiwać okolice i odkrywać kolejne lokacje, pukając do domów zbierając cukierki lub rozprawiając się z grasującymi tam potworami cukierkowymi w zabawnych potyczkach. Do towarzystwa zbieramy stopniowo kolejnych kompanów, odkrywamy przepisy i materiały na przydatne kostiumy Halloweenowe, które nie tylko przydają nam się w fabularnych zagadkach, ale też mają konkretne moce przydatne podczas potyczek z monstrami.

Potyczki przypominają trochę bitwy z Heroes III albo z niektórych j-rpg, polegają na tym, że aktualne kostiumy postaci zamieniają je niczym w Transformersach w przesadzone, nadmuchane wersje, które posiadają różne bojowe umiejętności i wrogowie stają naprzeciwko siebie na małym skrawku mapy. Pokonujemy wrogów mając wpływ na wybór umiejętności i wycelowując je w konkretnego wroga lub przyjaciela (są też umiejętności defensywne, pomocnicze) musimy wykonać w dobrym timingu prosty Quick Time Event (np. nacisnąć szybko jeden z przycisków pada).

Potyczki są dość proste, choć zabawne, służą również zdobywaniu przez bohaterów doświadczenia i po pewnym czasie zamieniają się w sposób na 'grind’, czyli monotonne tłuczenie tej samej mechaniki w celu podnoszenia poziomu postaci. Mimo to, są to dość satysfakcjonujące potyczki. Dodatkowo mamy dostęp do różnych minigierek, zagadek fabularnych prowadzących do odkrywania kolejnych lokacji. Gra jest całkiem sympatyczna, szczególnie w okresie Halloween, dostępny jest również sequel, w który jeszcze nie grałem.

I to by było na tyle, miało być szybko, może następnym razem 😉

Gra w odejmowanie – rozwiązanie.

Zgodnie z obietnicą przyszedł czas na odpowiedź na pytanie, jak żyć… znaczy grać. Jeśli udało Wam się wygrać w grze w odejmowanie piłeczek, to gratuluję, jeśli wygrywacie za każdym razem, to winszuję jeszcze bardziej i zapytuję dlaczego nie spróbowaliście nacisnąć zielonego przycisku? Tak, w wersji, w której komputer zaczyna nie da się wygrać. Komputer się nie myli i jego pierwszy ruch determinuje wygraną. Zatem, żeby wygrać trzeba zaczynać, zrobić dobry pierwszy ruch i konsekwentnie dobre wszystkie następne ruchy.
Dobre, czyli jakie, zapytacie?

Odpowiedź na to pytanie porusza ciekawe zagadnienie, które jakoś podświadomie od zawsze mnie interesowało. Chodzi o proces dochodzenia do rozwiązania jakiegoś zadania, zagadki czy problemu oraz stopień w jakim odkryte rozwiązanie naprawdę rozumiemy. Na pewno tylko dotknę tego tematu teraz, ale myślę, że będę do niego wracał już w następnych postach.

Miałem to szczęście, że pokazałem Grę w Odejmowanie kilku osobom i mogłem przyjrzeć się temu, jak podchodzą do rozwiązania problemu w niej zawartego. Parę osób było mi wcześniej nieznanych i tym bardziej nie mogłem nawet zgadywać, jak się zabiorą za zadanie. Pierwszym sposobem podejścia do rozwiązania była oczywiście metoda prób i błędów. Po obserwacji jakie ruchy prowadzą do jakich konsekwencji oraz przetestowaniu skrajnie prostych przypadków, osoba stosująca tę metodę dochodziła do wniosku, że np. trzeba wybierać za każdym razem 2 piłeczki. Co oczywiście czasem prowadziło do wygranej, a czasem nie. Jednak kilka prób wystarczyło, żeby usatysfakcjonować gracza wygraną. Oczywiście przy tej metodzie utrudnione zadanie mieli gracze ze skłonnością do wybierania opcji, że komputer zaczyna.

Zdarzył mi się jednak gracz, który zauważył, że skoro komputer zawsze wygrywa, jeśli zaczyna, to w tej opcji gry najłatwiej będzie mu sprawdzić, co robi komputer żeby wygrać, a później spróbuje to zastosować w swojej grze, czyli kiedy sam robi pierwszy ruch. No i rzeczywiście, po kilku próbach, okazało się, że prawdopodobnie komputer zawsze zaczyna od wzięcia dwóch piłeczek, a następnie jeśli my weźmiemy jedną, to on bierze dwie, jeśli zaś my bierzemy dwie, to on bierze jedną. Zawsze na odwrót, albo inaczej mówiąc, żeby, nie licząc pierwszego ruchu, ruch gracza i komputera w sumie zabierał trzy piłeczki.
I to jest właściwie prawidłowe rozwiązanie!

Ale czemu tak jest i czy naprawdę to rozumiemy? Możemy to sprawdzić, na przykład poprzez zwiększenie liczby piłeczek o 2, wtedy niby gra jest ta sama, ale biorąc na początku dwie piłeczki, zmieniamy grę w taką, jakby przy dwunastu piłeczkach zaczynał komputer. Dodatkowo możemy jeszcze bardziej utrudnić sobie i zwiększyć liczbę piłeczek, które można wziąć w jednym ruchu. Na przykład, co by było gdyby można było wziąć jedną, dwie lub trzy piłeczki.
Zachęcam do poeksperymentowania poniżej, przygotowałem specjalną wersję gry gdzie można ustawić dowolną liczbę piłeczek na początku i dowolną liczbę piłeczek do wzięcia w jednym ruchu. W ten sposób ustawiając te parametry na początku, tworzycie własną wersję gry z całego zbioru gier o zabieraniu piłeczek.

OK. Poeksperymentowaliśmy – czy nam to pomogło w zrozumieniu czy raczej zagmatwało sytuację bardziej? Zauważmy, jak ważne jest to kto zaczyna. Pierwszy ruch determinuje, kto weźmie dwunastą piłeczkę po jeszcze conajmniej pięciu ruchach. Jak z kolei wygląda końcówka? Żeby wygrać trzeba po prostu zostawić przeciwnikowi ostatnią piłeczkę. Jeśli zostały dwie, to bierzemy jedną. Jeśli zostały trzy, to bierzemy dwie. No a jeśli zostały cztery, to nie jesteśmy w stanie zostawić jednej, to co robimy? Niestety w tej sytuacji nie mamy już wyjścia i co nie zrobimy, to przeciwnik ma jeszcze szansę nie wziąć ostatniej piłeczki, bo zostawiamy mu więcej niż jedną, ale mniej niż cztery, więc ma w jednym ruchu możliwość pozostawienia nas z ostatnią piłeczką.

W tym momencie powinno nas olśnić, że jeśli zostawiamy przeciwnikowi ostatnią piłeczkę to wygrywamy, ale też kiedy zostawiamy mu do wzięcia czwartą piłeczkę, to też w jakimś sensie wygrywamy, wygrywamy pewien etap, który umożliwia nam wygranie kolejnego.

Zatem możemy spojrzeć na problem inaczej. Skoro trzeba wygrać czwartą od końca piłkę (wygrać czyli zmusić przeciwnika do jej wzięcia), żeby wygrać ostatnią, to możemy w myślach usunąć 3 ostatnie piłki i do tego etapu grać, jakby czwarta od końca piłka była ostatnią.
No i stąd prosty pomysł, żeby tak zrobić (w myślach) z kolejnymi grupami po trzy piłeczki, aż zostaną pierwsze trzy piłeczki (lub mniej). A tu problem jest prosty, trzeba wziąć tyle piłeczek, żeby została tylko jedna, wtedy wiemy na pewno, że przeciwnik ją weźmie, a z drugiej strony z następnej grupy zostawi nam więcej niż jedną.

I tak gramy, aż do samego końca. Na poniższym rysunku zobaczcie proszę, jak podzieliłem piłeczki na grupy. To samo trzeba zrobić myślowo podczas gry i konsekwentnie zostawiać ostatnią piłeczkę z każdej grupy przeciwnikowi.

Podzielcie sobie piłeczki na grupy po 3. Każdą ostatnią piłeczkę w grupie (zaznaczona na zielono) musi wziąć przeciwnik. Rys. 1 – Podział na grupy.

Spróbujcie teraz jeszcze raz zagrać w powyższą wersję gry i sprawdzić czy potraficie uogólnić ten sposób grania na dowolne liczby piłeczek.
Dla ułatwienie liczenia i dzielenia na grupy, dodałem informacje podczas gry ile piłeczek zostało i ile aktualnie jest wybranych przez Ciebie lub komputer.

Myślę, że na tym etapie jesteśmy już trochę zmęczeni tematem piłeczek i tej gry, więc pozwolę sobie go zakończyć na dłuższy czas mimo, że miałem jeszcze w planie opisać zagadnienie drzewa decyzji oraz eleganckiego matematycznie algorytmu gry. Zrobię to, ale może przy innej okazji, tymczasem trzeba iść do przodu!

Jak zwykle proszę o komentarze i ciekawą dyskusję 🙂

Aktualności i plany #1

Cześć!

Aktualnie zajmuję się rzeczami, które nie mają natychmiastowego wpływu na bloga. Następny post jest w trakcie tworzenia i jeszcze to potrwa, ponieważ jest dość pracochłonny. Stąd wpadłem na pomysł szybkiego wpisu, gdzie w powierzchowny sposób opiszę, co się u mnie dzieje.
Korzystając też z jeszcze nie gasnącego entuzjazmu noworocznego, snuję plany na najbliższą przyszłość.

AKTUALNOŚCI

  1. Finiszuję ten kurs na Courserze:
    Algorithms: Design and Analysis, part 1, wszystkie tygodnie zakończone pozytywnie, został tylko końcowy test. W tym celu powtarzam sobie wszystkie algorytmy i do 22.01 powinienem to zaliczyć.
  2. Ostro trenuję tenis stołowy, przeszedłem na reżim trzy treningi w tygodniu. Mini-cel: odbierać backspina topspinem, jeszcze mi to nie wychodzi tak często, jak bym chciał.
  3. Wersja 2.0 Gry w Odejmowanie jest praktycznie ukończona. Zawiera możliwość ustalenia parametrów startowych gry: ile jest w sumie piłeczek do wzięcia oraz ile można maksymalnie zabrać w jednym ruchu. Tworzy się jeszcze wersja 2.1, która będzie zawierała informacje o aktualnym stanie gry, tak żeby nie trzeba było liczyć piłeczek na ekranie.
  4. Grę w Odejmowanie publikuję na GitHubie tutaj.
  5. Aktualnie czytam: 
  6. Powtarzam CAŁĄ matematykę – ktoś ma ciekawe zadanie z podstawówki lub do matury, z chęcią przyjmę 🙂
    W tym celu pomaga mi dzielnie Khan Academy!

PLANY

  1. Do 22.01 chcę mieć już zdany test końcowy z Algorytmów i pochwalić się tym na LinkedIn 🙂
  2. Do końca stycznia planuję opublikować post z grą w piłeczki w nowej wersji 2.1 i krótką jej analizą.
  3. No a w lutym czas rozpocząć pracę nad nową grą! W sekrecie zdradzę, że ma to być gra ekonomiczna, trochę bardziej skomplikowana niż ta pierwsza, ale nadal będę starał się trzymać wyobraźnię w ryzach, by grę przede wszystkim ukończyć. Stawiam sobie termin do 25 maja (nieprzypadkowy, ale o tym kiedy indziej). Jest on dość odległy, więc na pewno będą update’y w międzyczasie oraz szczegółowszy plan, by czas się nie rozmydlił.
  4. By było co czytać, zanim nowa gra się ukaże, chcę zrobić dwa lżejsze, ale mam nadzieję równie wartościowe posty. Jeden o dość podstawowym zadaniu z liceum, które czasem sprawia kłopoty, a po latach okazało się, że jest na to wzór, więc nie warto się stresować.
    Drugi post, korzystając ze świeżej wiedzy z kursu algorytmicznego, będzie o liczeniu kroczącej mediany przy pomocy dwóch kopców i jeśli warto tak liczyć, to kiedy.
  5. Chcę publikować conajmniej jeden post miesięcznie, więc trzymajcie kciuki!
  6. Równolegle z tworzeniem nowej gry myślę nad kontynuacją specjalizacji Full Stack Web Development i trzecim kursem w jej ramach: Front-End JavaScript Frameworks: AngularJS. Może mnie bardzo wspomóc w rozwoju gry, która również będzie webowa.
  7. Kontynuuję powtórkę z matmy: w tym półroczu Algebra i Geometria 🙂

To wszystko na dziś – mam nadzieję, że ta publiczna deklaracja pomoże mi w realizacji celów. Trzymajcie kciuki, proszę!

Konferencja to brzmi dumnie

MTP

22 października odwiedziłem konferencję GIC w ramach PGA.
Ale, że co?!

Już tłumaczę skrótowce, których jakoś nigdy za dużo w naszej mowie, prawda?
Na zdjęciu widzicie jeden z budynków Międzynarodowych Targów Poznańskich z wywieszonym plakatem festiwalu Poznań Game Arena (pierwszy akronim rozwiązany). Festiwal dotyczy szeroko rozumianej kultury gier video i z przerwami odbywa się już od 2004 roku. W tym roku obejmował trzy dni od 21 do 23 października, z tym że pierwszy dzień to tak zwany VIPowski – głównie dla dziennikarzy i ludzi branży albo kogoś kto może pozwolić sobie na bilet za 120zł. W pozostałe dni bilety były w cenie 25zł.

To na pewno wielkie święto elektronicznej rozrywki. W tym roku odwiedziło PGA ponad 70 tysięcy osób. To kolejny rekordowy rok z rzędu. Mnóstwo wystawców sprzętu, deweloperów gier (zarówno niezależnych jak i wielkich wydawnictw), konkursy, sceny, możliwość wypróbowania gier w rzeczywistości wirtualnej, gier jeszcze niewydanych, symulatorów itd. Nie zabrakło nawet stanowiska z grami retro, które od lat tworzą zapaleńcy starych komputerów. Poniższe zdjęcie tylko w niewielkim stopniu oddaje skalę festiwalu i jak dużo osób go odwiedziło, bo to tylko jeden z wielu budynków, w których się odbywały. Po szerszą galerię odsyłam na stronę targów: www.gamearena.pl. Szczególnie polecam zdjęcia cosplayerek!

PGA

Moim głównym celem jednak nie było właściwe PGA. Jak się zresztą okazało w trakcie, bardzo słusznie. Już się nie nadaję (a może nigdy się nie nadawałem?) do manewrowania w tak wielkich tłumach, stania w długaśnych kolejkach, odpierania jazgotu mieszających się zewsząd dźwięków. Na samym, właściwym PGA byliśmy tylko przez godzinę, z czego połowę na stołówce. Notabene było bardzo smacznie.

Większość czasu na terenie Targów Poznańskich spędziliśmy na Game Industry Conference (drugi akronim wyjaśniony). To konferencja z założenia dla przedstawicieli firm z branży gier i twórców niezależnych, ale też dla osób dopiero aspirujących do tego miana lub wręcz kandydatów na konkretne stanowiska. Żeby dostać się na teren konferencji wystarczyło mieć bilet PGA, zatem każdy z ponad 70 tysięcy uczestników mógł uczestniczyć w prezentacjach i porozmawiać z przedstawicielami firm na ich osobnych stanowiskach. Po uprzednim zapisaniu można było nawet uczestniczyć w warsztatach z tworzenia gier czy spotkaniach o nazwie Pitch & Match, które tworzyły przestrzeń networkingową dla branżowców. Na szczęście, czy to może dzięki osobnemu budynkowi czy eleganckiej organizacji prezentacji w salach konferencyjnych, wielkiego tłumu nie było, na każdej prezentacji zawsze znalazło się wolne krzesło i większość dnia od godziny 10 do 19 spędziliśmy siedząc w ciepełku słuchając ciekawych prelegentów.
W pomieszczeniach o dźwięcznych nazwach jak Techland Hall czy Microsoft Hall opowiadano o aspektach technicznych, muzyce, tworzeniu grafiki, rekrutacji, fabule i narracji oraz promowaniu, programowaniu i sprzedawaniu, a nawet prawie.

Mój osobisty odbiór tego wydarzenia był sprofilowany moimi wyborami prelekcji i oczekiwaniami w stosunku do nich.
Przede wszystkim chciałem z punktu widzenia początkującego dewelopera gier dowiedzieć się, jakich umiejętności potrzebuje programista, a jakich game designer. Stąd najbardziej czekałem na “Jak zostać programistą w GameDevie” autorstwa Andrzeja Blumenfelda i Artura Janika z Techlandu oraz “The Path of Pain: mastering game design in 35 steps” Kacpra Szymczaka z Creative Forge. I właściwie na tym pierwszym nie zawiodłem się, a drugie mnie mocno zaskoczyło i to pozytywnie.

Dostałem bardzo konkretny zestaw wytycznych dla programistów:

  • język programowania to C++, bo kontrola i jeszcze raz kontrola – głównie nad pamięcią i wydajnością, blisko sprzętu; poza tym jest wieloplatformowy, istnieje mnóstwo bibliotek i narzędzi, cały czas jest rozwijany.
  • kontrola wersji to mus, na przykład Git, który jest teraz bardzo popularny.
  • robić gry, robić, ale nie wielkie projekty, których się nie da skończyć, tylko małe w Unreal/Unity, by uczyć się tworzyć elementy gameplayu
  • albo robić własne silniki gier i grafiki, by uczyć się technologii.
  • żeby nauczyć się programowania reakcji gry na gracza: stosować podstawowe techniki AI , takie jak maszyny stanów, drzewa zachowań, hierarchiczna sieć zadań.

Drugi wykład okazał się nie tyle poradnikiem dla projektantów gier, ile bardzo uniwersalnym przemówieniem motywacyjnym. Kacper Szymczak okazał się charyzmatycznym mówcą, dysponującym ciekawymi slajdami, filmikami, cytatami ze znanych tego świata i własnymi celnymi spostrzeżeniami.
Tutaj można poczuć jego moc: The Path of Pain, myślę, że warto.
Będąc już lekko zmęczonym i oszołomionym całym dniem na GIC, prezentacja głównego projektanta Creative Forge dała mi pozytywnego kopa emocjonalnego i pozwoliła uwierzyć, że jeśli nawet czuję ból nieprzynależenia i stawiania pierwszych kroków w nieznane, to znaczy, że idę w dobrym kierunku, a od uczuć tych nie należy uciekać, tylko zaakceptować, głęboko poczuć i potraktować jako dowód wartości obranej ścieżki.
No pain, no gain! – jak to mówią.

Z pozostałych wykładów, na których byliśmy, opowiem jeszcze tylko o dwóch. Znowu para: technologia i design. Interesowały mnie one ze względu na możliwość zastosowania przeze mnie w najbliższym czasie w jakimś moim małym projekcie gry.
Aleksandr Kudishov przybył na GIC z wykładem “Photogrammetry – an easy way of using great technology”. Fotogrametria, czyli mierzenie przy pomocy zdjęć jest technologią używaną w różnych dyscyplinach. W grach wideo służy do przenoszenia obiektów świata rzeczywistego, jako trójwymiarowe modele do komputera wraz z gotowymi teksturami, dzięki czemu umożliwia stosowanie ich wielokrotnie przy budowie świata gry. Użyta była na przykład w przygodówce „The Vanishing Of Ethan Carter”. Spodziewałem się, że zaletą tej technologii może być, oprócz fotorealistycznej grafiki, pewna oszczędność przy tworzeniu obiektów do gry. Niestety pomimo wrażenia, że autor ma dużą wiedzę popartą praktycznym doświadczeniem, nie wyniosłem zbyt dużo z prezentacji z powodu silnego rosyjskiego akcentu, który mimo moich najszczerszych chęci, mocno szyfrował treść wypowiedzi. Na szczęście udało mi się zrobić kilka zdjęć slajdów z czego najciekawsze to wady i zalety fotografowania w studiu i na zewnątrz, użyte programy i sprzęt czy porady dot. kątów robienia zdjęć. Resztę wiedzy zdobędę samodzielnie na tej podstawie.

Z kolei wystąpienie Igora Hardy’ego z niezależnego Dreamgrit było całkowicie zrozumiałe mimo, że po angielsku i nosiło obiecujący tytuł: “What can game storytelling learn from Improv Theatre?”. Dużo tu było dla mnie nowego, szczególnie wiadomości o teatrze improwizacji, w którym udziela się prelegent i jakimi zasadami się rządzi. Przejście od teatru do gier było dość zaskakujące, bo skupiało się w dużej mierze na analizie opowiadanych historii w grach symulacyjnych niż w grach bardziej kojarzonych z fabułą, takich jak chociażby przygodowe. Tym bardziej wyostrzyłem słuch, bo mam pewne pomysły na oba typy gier, ale nie myślałem wcześniej, żeby to połączyć. Nie jest to pomysł do końca nowy, jego dobrą realizację można zobaczyć w ostatnim hicie polskiego studia 11bit studios, pod tytułem “This War Of Mine”.

I to by było na tyle, jeśli chodzi o moje osobiste sprawozdanie z Game Industry Conference i Poznań Game Arena. Napakowany inspiracją i wiadomościami, pozostaje mi tylko kontynuować rozpoczętą przygodę, ahoj!
Dodam tylko, że miasto Poznań okazało się bardzo sympatycznym gospodarzem targów, choć droidów astromechanicznych nie darzą tu sympatią…

R2D2

Na początku była gra…

Cześć!

Bez zbędnych ceregieli – po co ten blog, dlaczego, jak często – przechodzę do sedna…
I do prezentu dla moich pierwszych Czytelników.

Od kiedy interesuję się komputerami, czyli od dzieciństwa w latach 80-tych, pierwszym i najważniejszym zastosowaniem komputera były dla mnie gry.

Wiele się od tamtego czasu zmieniło, komputer stał się dla mnie narzędziem codziennej pracy, a to jak stał się ogólnie powszechny spowodowało, że trochę zacząłem zapominać jaki zachwyt wzbudzał we mnie kiedyś, gdy mimo 64KB pamięci pod maską i 2MHz procesora przenosił mnie w inne wspaniałe światy, stawiał przede mną wyzwania intelektualne i manualne.

Twórcy gier jawili się dla mnie wtedy, jak wspaniali magicy, poeci,świetni muzycy i błyskotliwi inżynierowie w jednym. Marzenia o staniu się jednym z takich geniuszy wydawały się nieuzasadnione. Przecież moja gra nie będzie się równała z ich grami, nie umiem tak dobrze programować, nie znam się na grafice, nie mam talentu muzycznego, itd…

Czasem stawiamy sobie ograniczenia, które nie pozwalają nam po prostu czerpać radości z tego, co naprawdę lubimy robić.
A tworzenie gier jest jeszcze większą radością niż granie w nie.
A tworzenie gier, w które ktoś z chęcią gra, to już szczyt spełnienia.

Czy można robić pierwsze gry mając prawie czterdziestkę?
Można, tak jak można zacząć malować, śpiewać, biegać czy majsterkować.
Po prostu należy przestać marzyć…

Dlatego zapraszam do zagrania poniżej w moją pierwszą grę, która jest inspirowana znaną zabawą.
Zasady są następujące:

  • Mamy 12 piłek w rzędzie, z których ostatnia jest specjalna, bo jest bombą!
  • Wybieramy, kto zaczyna – my czy komputer.
  • Gracze robią ruchy na zmianę, które polegają na zabraniu jednej lub dwóch piłek.
  • Kto zabierze ostatnią piłkę – bombę, przegrywa.

Zagrajcie przeciw komputerowi i zobaczcie, czy i kiedy potraficie z nim wygrać.


Mam nadzieję, że gra sprawiła Wam choć chwilę radości, tak jak mnie sprawiła wiele radości praca nad nią. Ta prosta gra została zrobiona w HTML’u i Javascripcie, którego się aktualnie uczę.

Zanim usiadłem do programowania, zrobiłem sobie mały projekt gry, taki dokument, który w świecie twórców gier, zwany jest GDD – Game Design Document. To jest bardzo przydatny etap robienia gry.
Gdy mam już przemyślane i spisane, jak gra ma wyglądać, jakie są ekrany, jak wyglądają ruchy gracza i komputera, jaki jest algorytm gry, implementacja jest już znacznie prostsza – wiem do czego dążę i skupiam się już tylko na problemach technicznych. Oczywiście po drodze wyszły dwa zagadnienia, których nie przewidziałem, pod względem mechaniki gry, ale to były już małe rzeczy, większość miałem już dobrze przemyślane.

W GDD wypisałem kilka dodatkowych atrakcji, których nie zaimplementowałem, bo wydłużały proces programowania, a nie były istotą gry. Chciałem przede wszystkim grę skończyć!
Gra nie ma zbyt dużej „regrywalności”, jak się zorientujecie, jak w nią wygrywać, to właściwie koniec zabawy. Dlatego zachęcam do komentowania – czy była dla Was zaskoczeniem, czy chcecie żebym ją dalej rozszerzał o nietknięte pomysły z GDD, albo zgłaszajcie własne pomysły, jak grę wzbogacić.
A może chcielibyście przeczytać, jak w grę wygrać i dlaczego w ten sposób, oraz jak gra komputer, a także jak nauczyć komputer w nią grać.
Ten drugi temat na pewno i tak podejmę na blogu, od Was zależy, który najpierw.

Także komentujcie, wybierajcie, sugerujcie!

P.S. Dla zainteresowanych JavaScriptem: okazuje się, że ruch jest względny, zdarzenie onMouseOut jest generowane nie tylko przez kursor uciekający znad obiektu, ale też obiekt usunięty z DOM, który był pod kursorem…

Icons made by Madebyoliver from www.flaticon.com is licensed by CC 3.0 BY
Icons made by Freepik from www.flaticon.com is licensed by CC 3.0 BY
Icons made by Roundicons from www.flaticon.com is licensed by CC 3.0 BY