\documentclass[a4paper,10pt]{article}
\usepackage{amsmath}                    % Lisäyksiä LaTeXin matematiikkatukeen
%\usepackage{SIunits}                   % Tuki SI-yksiköille (esim. \meter\per\second)
\usepackage[latin1]{inputenc}           % Ääkköstuki
%\usepackage{color}                     % Tuki väritetylle tekstille
\usepackage{array}
\usepackage{multirow}                   % Tuki useita rivejä kattaville taulukkoelementeille
\usepackage[finnish]{babel}             % Suomenkielinen lokalisaatio
\usepackage{graphicx}                   % Tuki EPS-kuville

% ---
% Tästä voit muokata sivun marginaaleja.
% ---
\addtolength{\evensidemargin}{-1cm}
\addtolength{\oddsidemargin}{-1cm}
\addtolength{\textwidth}{2cm}
\addtolength{\topmargin}{-0.5in}
\addtolength{\textheight}{0.5in}
\setlength{\parindent}{0in}             % Kappaleiden sisennys pois päältä
\setlength{\parskip}{6pt plus 4pt minus 6pt}               % Tyhjää tilaa kappaleiden välillä

% ---
% Ohjeita LaTeXin käyttöön esimerkiksi täältä: http://www.andy-roberts.net/misc/latex/
% LaTeX-editoreja: http://en.wikipedia.org/wiki/LaTeX#Editors_and_IDEs
% ---

\begin{document}

% ---
% Otsikkosivu. Tämä olisi kiva toteuttaa käyttäen hyväksi LaTeXin ohjelmoitavuutta.
% ---

\begin{center}
Tampereen teknillinen yliopisto

Ohjelmistotekniikan laitos
\vspace{4cm}

\rule{4.5in}{0.4mm}

\begin{Huge}
OHJ-1101

Ohjelmointi Ie
\end{Huge}

\vspace{0.4cm}
\begin{Large}
Harjoitustyö

\vspace{-2mm}
Ataxx

\vspace{-1mm}
Välipalautus
\end{Large}
\rule{4.5in}{0.4mm}

\vspace{4cm}
% Muuta nämä!
Tuomo Turunen
 
9.1.2008 13:15 TB211
\end{center}

\vfill
Petteri Aimonen (205441)

\vspace{-2mm}
aimonen

\vspace{-2mm}
petteri.aimonen@tut.fi
\newpage

% -----------------------
% Kappaleet alkavat tästä
% -----------------------

% ---
% Esimerkki EPS-muotoon tallennetun UML-kaavion liittämisestä dokumenttiin.
% Huomaa, että EPS-kuvia käytettäessä suora käännös PDF-muotoon 'pdflatex':lla
% ei onnistu (ainakaan ilman kikkailua). Käännös tulee suorittaa ensin DVI-muotoon,
% mistä edelleen PDF:ksi. Muita kuvamuotoja käytettäessä tilanne on ymmärtääkseni
% päinvastainen, eli ainoastaan 'pdflatex' toimii.
% ---
%\section*{UML-kaavio}
%\begin{center}
%\includegraphics[scale=0.6, trim = 0 0 0 0, clip]{classes2}
%\end{center}

\section{Ohjelman rakenne}

\subsection{Ohjelman tietorakenteet}

Pelilauta tallennetaan 7x7 taulukkona, jonka alkioina enumeja. Taulukossa ensimmäinen indeksi on x-koordinaatti, ja jälkimmäinen y-koordinaatti.
\begin{verbatim}
const int LAUDAN_KOKO = 7;
enum Nappula {TYHJA, VALKOINEN, MUSTA};
Nappula pelilauta[LAUDAN_KOKO][LAUDAN_KOKO] = {{TYHJA}};
\end{verbatim}

Siirrot kuvataan structilla, jossa on lähtö- ja kohdekoordinaatit. Structissa koordinaatit on tallennettu taulukon indeksoinnin mukaan, eli pienin arvo on 0 ja suurin {\bf LAUDAN\_KOKO} - 1.
\begin{verbatim}
struct Siirto {
    int alkuX, alkuY;
    int loppuX, loppuY;
};
\end{verbatim}

Replay-komennot tallennetaan pääohjelmassa määriteltyyn ostringstreamiin sitä mukaa kun komentoja syötetään. Stringistä ne voidaan sitten tallentaa lopuksi tiedostoon, tai jättää tallentamatta.
\begin {verbatim}
ostringstream replaykomennot("");
\end{verbatim}


\subsection{Funktioiden kutsukaavio}
\includegraphics[scale=0.5]{kutsusuhteet.eps}

\section{Funktioiden kuvaukset}

\subsection{Pääohjelma}
Ennen peliä pääohjelma kysyy pelaajien nimet, alustaa vuoroksi valkoisen pelaajan ja alustaa pelilaudan {\bf alustalauta}-funktiolla. Pelaajien nimet tallennetaan replaykomentoihin.

Pelin aikana pääohjelma tekee loopissa seuraavat asiat:
\begin{enumerate}
\item Tarkistetaan onko peli päättynyt funktion {\bf peliloppu} avulla.
\item Tulostetaan vuorossa olevan pelaajan nimi sekä laudan tilanne.
\item Jos vuorossa oleva pelaaja on tietokonepelaaja, etsitään siirto funktiolla {\bf ai\_etsisiirto}. Muussa tapauksessa luetaan siirto. Jos {\bf luesiirto} palauttaa falsen, lopetetaan peli.
\item Toteutetaan siirto.
\item Tallennetaan siirto replaykomentoihin.
\item Vaihdetaan vuorossa olevaa pelaajaa.
\end{enumerate}

Pelin jälkeen tulostetaan lauta ja tarkistetaan tilanne {\bf laskepisteet}-funktiolla. Tulostetaan viesti voittajasta/tasapelistä.

Lopuksi kysytään replay-tiedoston tallennusta. Tiedostoon tallennetaan {\bf replaykomennot}-muuttujan sisältö.

\subsection{Funktio: alustalauta}
{\em Esittely:}\\
{\tt void alustalauta(Nappula pelilauta[][]);}

{\em Parametrit:}\\
Parametri {\bf pelilauta} on taulukko, johon pelilauta alustetaan.

{\em Paluuarvo:}\\
Funktio ei palauta arvoa.

{\em Toiminta:}\\
Aluksi lauta käydään läpi, ja asetetaan kaikkiin paikkoihin tyhjä. Sitten kulmapaikkoihin asetetaan nappulat, vasempaan alakulmaan ja oikeaan yläkulmaan MUSTA, ja vasempaan yläkulmaan ja oikeaan alakulmaan VALKOINEN.

{\em Käyttö:}\\
Pääohjelma kutsuu funktiota ennen pelin alkua.

\subsection{Funktio: tulostalauta}
{\em Esittely:}\\
{\tt void tulostalauta(const Nappula pelilauta[][]);}

{\em Parametrit:}\\
Parametri {\bf pelilauta} on taulukko, jossa on pelilaudan tilanne siirtojen tarkistamista varten.

{\em Paluuarvo:}\\
Funktio ei palauta arvoa.

{\em Toiminta:}\\
Aluksi tulostetaan yläakseli. Sen jälkeen taulukko käydään riveittäin läpi, joka rivin alkuun tulostetaan rivinumero ja sen perään laudan paikkoja vastaavat symbolit.

{\em Käyttö:}\\
Pääohjelma kutsuu funktiota ennen siirtoa, sekä pelin loputtua.


\subsection{Funktio: luesiirto}

{\em Esittely:}\\
{\tt bool luesiirto(const Nappula pelilauta[][], Nappula vuoro, Siirto \&tulos);}

{\em Parametrit:}\\
Parametri {\bf pelilauta} on taulukko, jossa on pelilaudan tilanne siirtojen tarkistamista varten. \\
Parametri {\bf vuoro} on vuorossa olevan pelaajan väri (arvo TYHJA ei ole sallittu). \\
Parametri {\bf tulos} on Siirto-tyyppinen struct, johon luetut koordinaatit tallennetaan.

{\em Paluuarvo:}\\
Jos syötettiin negatiivinen lähtöruudun x-koordinaatti (= pelin lopetus), palautetaan {\bf false}. Muissa virhetilanteissa tulostetaan virheilmoitus ja kysytään koordinaatteja uudelleen. Onnistuneen syötteen jälkeen palautetaan {\bf true}.

{\em Toiminta:}\\
Koordinaatit kysytään käyttäjältä {\bf cin} ja {\bf cout}-virtojen kautta. Kun koordinaatit on luettu, ne tallennetaan taulukon indekseiksi muutettuina Siirto-structiin. Jos lähtöpaikan x-koordinaattia luettaessa tulos on negatiivinen, palautetaan heti {\bf false}. Muutoin luettu siirto välitetään pelilaudan ja vuoron kanssa funktiolle {\bf tarkistasiirto}.

Jos siirto oli laillinen, palautetaan {\bf true}. Muussa tapauksessa {\bf tarkistasiirto} on tulostanut virheilmoituksen, joten riittää kysyä koordinaatteja uudelleen.

{\em Käyttö:}\\
Pääohjelma kutsuu funktiota loopissa, kunnes peli loppuu.

\subsection{Funktio: tarkistasiirto}

{\em Esittely:}\\
{\tt bool tarkistasiirto(const Nappula pelilauta[][], Nappula vuoro, const Siirto \&siirto);}

{\em Parametrit:}\\
Parametri {\bf pelilauta} on taulukko, jossa on pelilaudan tilanne. \\
Parametri {\bf vuoro} on vuorossa olevan pelaajan väri (arvo TYHJA ei ole sallittu). \\
Parametri {\bf siirto} on tarkistettava siirto.

{\em Paluuarvo:}\\
Jos siirto oli laillinen senhetkisessä tilanteessa, palautetaan {\bf true}. Muutoin palautetaan {\bf false}.

{\em Toiminta:}
\begin{enumerate}
\item Tarkistetaan, että lähtö- ja kohdekoordinaatit ovat laudalla kutsumalla funktiota {\bf tarkistakoordinaatit}. Elleivät olleet, tulostetaan virhe aiheesta ja palautetaan {\bf false}.
\item Tarkistetaan, että lähtöruudussa on nappula.
\item Tarkistetaan, että lähtöruudussa oleva nappula on oma.
\item Tarkistetaan, että kohderuutu on tyhjä.
\item Tarkistetaan, että funktion {\bf siirronpituus} laskema siirtymä kohderuutuun on enintään 2 ruutua (= hyppy).
\item Jos virheitä ei havaittu, palautetaan {\bf true}
\end{enumerate}

{\em Käyttö:}\\
Funktio {\bf luesiirto} kutsuu funktiota siirron tarkistamiseksi.

\subsection{Funktio: tarkistakoordinaatit}
{\em Esittely:}\\
{\tt bool tarkistakoordinaatit(int x, int y);}

{\em Parametrit:}\\
Parametrit {\bf x} ja {\bf y} ovat koordinaatit, joiden kuuluminen pelilautaan tarkistetaan.

{\em Paluuarvo:}\\
Jos sijainti on pelilaudalla, palautetaan {\bf true}. Muutoin palautetaan {\bf false}.

{\em Toiminta:}\\
Kumpaakin koordinaattia verrataan alarajaan {\bf 0} ja ylärajaan {\bf LAUDAN\_KOKO} - 1.

{\em Käyttö:}\\
Funktio {\bf tarkistasiirto} tarkistaa lähtöpaikan ja kohdepaikan koordinaatit tällä funktiolla.

\subsection{Funktio: siirronpituus}
{\em Esittely:}\\
{\tt int siirronpituus(const Siirto \&siirto);}

{\em Parametrit:}\\
Parametri {\bf siirto} on siirto, jonka pituus lasketaan.

{\em Paluuarvo:}\\
Paluuarvo on siirron pituus siirron tyypin mukaan seuraavasti: {\bf 1} = kloonaus, {\bf 2} = hyppy, {\bf muut arvot} = laiton siirto.

{\em Toiminta:}\\
Paluuarvo on suurempi x-koordinaattien ja y-koordinaattien erojen itseisarvoista. Eli x-ero -2, y-ero 1 tuottaa pituuden 2.

{\em Käyttö:}\\
Funktio {\bf tarkistasiirto} käyttää tätä funktiota siirron laillisuuden määrittämiseen ja {\bf toteutasiirto} siirron tyypin määrittämiseen.

\subsection{Funktio: toteutasiirto}

{\em Esittely:}\\
{\tt void toteutasiirto(Nappula pelilauta[][], const Siirto \&siirto);}

{\em Parametrit:}\\
Parametri {\bf pelilauta} on taulukko, jossa on pelilaudan tilanne. \\
Parametri {\bf siirto} on suoritettava siirto.

{\em Paluuarvo:}\\
Funktio ei palauta arvoa.

{\em Toiminta:}\\
Siirto oletetaan lailliseksi. Lähtöruudussa ollut arvo kirjoitetaan kohderuutuun. Jos siirron pituus on 2 yksikköä, tyhjennetään lähtöruutu. Vierekkäiseen ruutuun siirryttäessä nappula kloonautuu. Sitten vaihdetaan kaikki kohderuudun ympäristössä olevat ei-tyhjät paikat siirretyn nappulan värisiksi.

{\em Käyttö:}\\
Pääohjelma kutsuu funktiota siirron lukemisen jälkeen.

\subsection{Funktio: peliloppu}

{\em Esittely:}\\
{\tt bool peliloppu(Nappula vuoro, const Nappula pelilauta[][]);}

{\em Parametrit:}\\
Parametri {\bf vuoro} on vuorossa oleva pelaaja.\\
Parametri {\bf pelilauta} on taulukko, jossa on pelilaudan tilanne.

{\em Paluuarvo:}\\
Jos pelilauta on täysi, sillä on vain yhden pelaajan nappuloita, tai nykyisellä pelaajalla ei ole siirtomahdollisuutta, palautetaan {\bf true}. Muutoin palautetaan {\bf false}.

{\em Toiminta:}\\
Mahdollisten siirtojen määrä tarkistetaan funktiolla {\bf mahdollisetsiirrot}. Jos mahdollisia siirtoja on 0, palautetaan heti {\bf true}.

Tämän jälkeen pelilauta tutkitaan järjestyksessä läpi. Arvo {\bf false} palautetaan heti, kun on löytynyt ainakin yksi kummankin pelaajan nappula, sekä yksi tyhjä ruutu. Ellei laudalta löydy jotain näistä, palautetaan läpikäynnin jälkeen {\bf true}.

{\em Käyttö:}\\
Pääohjelma kutsuu funktiota siirron jälkeen laudan tilanteen tarkistamiseksi.

\subsection{Funktio: laskepisteet}

{\em Esittely:}\\
{\tt void laskepisteet(int \&valkoinen, int \&musta, const Nappula pelilauta[][]);}

{\em Parametrit:}\\
Parametrit {\bf valkoinen} ja {\bf musta} ovat viittaukset, joiden kautta laskennan tulos tallennetaan.\\
Parametri {\bf pelilauta} on taulukko, jossa on pelilaudan tilanne.

{\em Paluuarvo:}\\
Funktio ei palauta arvoa.

{\em Toiminta:}\\
Pelilauta käydään järjestyksessä läpi, ja mustat ja valkoiset nappulat lasketaan.

{\em Käyttö:}\\
Pääohjelma kutsuu funktiota pelin päätyttyä voittajan selvittämiseksi.

\subsection{Funktio: mahdollisetsiirrot}

{\em Esittely:}\\
{\tt int mahdollisetsiirrot(std::vector<Siirto> \&siirrot, Nappula vuoro, const Nappula pelilauta[][]);}

{\em Parametrit:}\\
Parametri {\bf siirrot} on vektori, johon löydetyt siirrot tallennetaan.\\
Parametri {\bf vuoro} on pelaaja, jonka siirtoja etsitään.\\
Parametri {\bf pelilauta} on taulukko, jossa on pelilaudan tilanne.

{\em Paluuarvo:}\\
Paluuarvo on löydettyjen siirtojen lukumäärä.

{\em Toiminta:}\\
Pelilauta käydään järjestyksessä läpi. Jokaisen löydetyn ko. pelaajalle kuuluvan nappulan kohdalla tutkitaan siitä joka suuntaan 2 nappulaa. Jokaista tältä alueelta löytynyttä tyhjää ruutua kohti tallennetaan siirto vektoriin ja kasvatetaan laskuria.

{\em Käyttö:}\\
Funktio {\bf peliloppu} tarkistaa tällä funktiolla, voiko pelaaja tehdä siirtoja. Tekoäly käyttää tätä funktiota mahdollisten siirtojen hakemiseen.

\subsection{Funktio: ai\_etsisiirto}

{\em Esittely:}\\
{\tt void ai\_etsisiirto(Siirto \&tulos, Nappula vuoro, const Nappula pelilauta[][]);}

{\em Parametrit:}\\
Parametri {\bf tulos} on Siirto-structi, johon paras siirtovaihtoehto tallennetaan.\\
Parametri {\bf vuoro} on pelaaja, jonka siirtoa etsitään.\\
Parametri {\bf pelilauta} on taulukko, jossa on pelilaudan tilanne.

{\em Paluuarvo:}\\
Funktio ei palauta arvoa.

{\em Toiminta:}\\
Funktio kutsuu funktiota {\bf ai\_rekursio} sopivalla alkusyvyydellä, ja löytynyt siirto palautetaan suoraan.

{\em Käyttö:}\\
Pääohjelma käyttää funktiota, jos toinen tai molemmat pelaajat ovat tekoälyn ohjaamia.

\subsection{Funktio: ai\_rekursio}

Funktio etsii parhaan mahdollisen siirron. Periaatteena on käydä siirrot läpi, ja jokaisen siirron kohdalla tutkia, mitä vastapelaaja tekisi sen jälkeen. Kun on tutkittu {\bf syvyys} seuraavaa siirtoa, siirtoketjun hyvyys määritetään pelilaudan pistetilanteesta.

{\em Esittely:}\\
{\tt int ai\_rekursio(Siirto \&tulos, Nappula vuoro, const Nappula pelilauta[][], int syvyys);}

{\em Parametrit:}\\
Parametrit {\bf tulos}, {\bf vuoro} ja {\bf pelilauta} ovat samat kuin funktiossa {\bf ai\_etsisiirto}.\\
Parametri {\bf syvyys} rajoittaa haun syvyyttä. Jos arvo on 0, rekursio pysähtyy.

{\em Paluuarvo:}\\
Paluuarvo kuvaa löydetyn siirron hyvyyttä siten, että suurempi arvo on parempi siirto ko. pelaajan kannalta.

{\em Toiminta:}\\
Mahdolliset siirrot haetaan funktiolla {\bf mahdollisetsiirrot}. Jos syvyys on 0 tai mahdollisia siirtoja ei ole, lasketaan nappulat funktiolla {\bf laskepisteet}. Palautettava arvo on se, montako nappulaa enemmän pelaajalla {\bf vuoro} on kuin vastapelaajalla.

Jokainen mahdollinen siirto käydään läpi seuraavasti:
\begin{enumerate}
\item Muodostetaan kopio pelilaudasta.
\item Toteutetaan siirto pelilaudan kopioon.
\item Kutsutaan {\bf ai\_rekursio}:ta vastapelaajan vuorolla, pelilaudan kopiolla ja yhtä pienemmällä syvyydellä.
\item Paluuarvo on tulostilanteen hyvyys vastapelaajan kannalta, eli sen vastaluku on haluttu hyvyysluku.
\item Jos toteutettu siirto tuotti omalta kannalta parhaan tilanteen tähän mennessä, tallennetaan se muuttujaan {\bf tulos}, ja sen hyvyys väliaikaismuuttujaan.
\end{enumerate}

Lopuksi löytyneen parhaan siirron hyvyys palautetaan.

{\em Käyttö:}\\
Funktio {\bf ai\_etsisiirto} käyttää tätä funktiota varsinaiseen siirron etsintään.

\end{document} 
