From 9c2a69c727c470ad7410e1865f4155ebc143e22d Mon Sep 17 00:00:00 2001
From: ElektriikAtk <songohansmaka@gmail.com>
Date: Wed, 6 Mar 2024 15:38:30 +0100
Subject: [PATCH] Adrian push

---
 {list => Uppgift-2-Lista}/.gitkeep            |   0
 {list => Uppgift-2-Lista}/a.out               | Bin
 {list => Uppgift-2-Lista}/catch.hpp           |   0
 {list => Uppgift-2-Lista}/linked_list.cc      |   0
 {list => Uppgift-2-Lista}/linked_list.h       |   0
 {list => Uppgift-2-Lista}/linked_list.h.gch   | Bin
 {list => Uppgift-2-Lista}/linked_list1.cc     |   0
 {list => Uppgift-2-Lista}/linked_list1.h      |   0
 {list => Uppgift-2-Lista}/linked_list_test.cc |   0
 {list => Uppgift-2-Lista}/test_main.cc        |   0
 {list => Uppgift-2-Lista}/test_main.o         | Bin
 Uppgift-3-Spel/full_game/Code/constants.h     |  18 +++
 Uppgift-3-Spel/full_game/Code/entity.cc       |  38 +++++
 Uppgift-3-Spel/full_game/Code/entity.h        |  52 +++++++
 Uppgift-3-Spel/full_game/Code/game.cc         |  90 ++++++++++++
 Uppgift-3-Spel/full_game/Code/game.h          |  56 ++++++++
 .../full_game/Code/ghost_wrapper.cc           | 108 ++++++++++++++
 Uppgift-3-Spel/full_game/Code/ghost_wrapper.h |  52 +++++++
 Uppgift-3-Spel/full_game/Code/given.h         |   6 +
 Uppgift-3-Spel/full_game/Code/grid.cc         | 135 ++++++++++++++++++
 Uppgift-3-Spel/full_game/Code/grid.h          |  59 ++++++++
 Uppgift-3-Spel/full_game/Code/pacman.cc       |  92 ++++++++++++
 Uppgift-3-Spel/full_game/Code/pacman.h        |  52 +++++++
 Uppgift-3-Spel/full_game/Makefile             |  15 ++
 Uppgift-3-Spel/full_game/README.md            |  14 ++
 Uppgift-3-Spel/full_game/main.cc              |  20 +++
 Uppgift-3-Spel/full_game/map.txt              |  22 +++
 Uppgift-3-Spel/ghost.h                        |  74 ++++++++++
 Uppgift-3-Spel/given.cc                       |  46 ++++++
 Uppgift-3-Spel/given.h                        |  62 ++++++++
 Uppgift-3-Spel/main.cc                        | 112 +++++++++++++++
 ghost.h                                       |  76 ----------
 32 files changed, 1123 insertions(+), 76 deletions(-)
 rename {list => Uppgift-2-Lista}/.gitkeep (100%)
 rename {list => Uppgift-2-Lista}/a.out (100%)
 rename {list => Uppgift-2-Lista}/catch.hpp (100%)
 rename {list => Uppgift-2-Lista}/linked_list.cc (100%)
 rename {list => Uppgift-2-Lista}/linked_list.h (100%)
 rename {list => Uppgift-2-Lista}/linked_list.h.gch (100%)
 rename {list => Uppgift-2-Lista}/linked_list1.cc (100%)
 rename {list => Uppgift-2-Lista}/linked_list1.h (100%)
 rename {list => Uppgift-2-Lista}/linked_list_test.cc (100%)
 rename {list => Uppgift-2-Lista}/test_main.cc (100%)
 rename {list => Uppgift-2-Lista}/test_main.o (100%)
 create mode 100644 Uppgift-3-Spel/full_game/Code/constants.h
 create mode 100644 Uppgift-3-Spel/full_game/Code/entity.cc
 create mode 100644 Uppgift-3-Spel/full_game/Code/entity.h
 create mode 100644 Uppgift-3-Spel/full_game/Code/game.cc
 create mode 100644 Uppgift-3-Spel/full_game/Code/game.h
 create mode 100644 Uppgift-3-Spel/full_game/Code/ghost_wrapper.cc
 create mode 100644 Uppgift-3-Spel/full_game/Code/ghost_wrapper.h
 create mode 100644 Uppgift-3-Spel/full_game/Code/given.h
 create mode 100644 Uppgift-3-Spel/full_game/Code/grid.cc
 create mode 100644 Uppgift-3-Spel/full_game/Code/grid.h
 create mode 100644 Uppgift-3-Spel/full_game/Code/pacman.cc
 create mode 100644 Uppgift-3-Spel/full_game/Code/pacman.h
 create mode 100644 Uppgift-3-Spel/full_game/Makefile
 create mode 100644 Uppgift-3-Spel/full_game/README.md
 create mode 100644 Uppgift-3-Spel/full_game/main.cc
 create mode 100644 Uppgift-3-Spel/full_game/map.txt
 create mode 100644 Uppgift-3-Spel/ghost.h
 create mode 100644 Uppgift-3-Spel/given.cc
 create mode 100644 Uppgift-3-Spel/given.h
 create mode 100644 Uppgift-3-Spel/main.cc
 delete mode 100644 ghost.h

diff --git a/list/.gitkeep b/Uppgift-2-Lista/.gitkeep
similarity index 100%
rename from list/.gitkeep
rename to Uppgift-2-Lista/.gitkeep
diff --git a/list/a.out b/Uppgift-2-Lista/a.out
similarity index 100%
rename from list/a.out
rename to Uppgift-2-Lista/a.out
diff --git a/list/catch.hpp b/Uppgift-2-Lista/catch.hpp
similarity index 100%
rename from list/catch.hpp
rename to Uppgift-2-Lista/catch.hpp
diff --git a/list/linked_list.cc b/Uppgift-2-Lista/linked_list.cc
similarity index 100%
rename from list/linked_list.cc
rename to Uppgift-2-Lista/linked_list.cc
diff --git a/list/linked_list.h b/Uppgift-2-Lista/linked_list.h
similarity index 100%
rename from list/linked_list.h
rename to Uppgift-2-Lista/linked_list.h
diff --git a/list/linked_list.h.gch b/Uppgift-2-Lista/linked_list.h.gch
similarity index 100%
rename from list/linked_list.h.gch
rename to Uppgift-2-Lista/linked_list.h.gch
diff --git a/list/linked_list1.cc b/Uppgift-2-Lista/linked_list1.cc
similarity index 100%
rename from list/linked_list1.cc
rename to Uppgift-2-Lista/linked_list1.cc
diff --git a/list/linked_list1.h b/Uppgift-2-Lista/linked_list1.h
similarity index 100%
rename from list/linked_list1.h
rename to Uppgift-2-Lista/linked_list1.h
diff --git a/list/linked_list_test.cc b/Uppgift-2-Lista/linked_list_test.cc
similarity index 100%
rename from list/linked_list_test.cc
rename to Uppgift-2-Lista/linked_list_test.cc
diff --git a/list/test_main.cc b/Uppgift-2-Lista/test_main.cc
similarity index 100%
rename from list/test_main.cc
rename to Uppgift-2-Lista/test_main.cc
diff --git a/list/test_main.o b/Uppgift-2-Lista/test_main.o
similarity index 100%
rename from list/test_main.o
rename to Uppgift-2-Lista/test_main.o
diff --git a/Uppgift-3-Spel/full_game/Code/constants.h b/Uppgift-3-Spel/full_game/Code/constants.h
new file mode 100644
index 0000000..b977ac6
--- /dev/null
+++ b/Uppgift-3-Spel/full_game/Code/constants.h
@@ -0,0 +1,18 @@
+#ifndef CONSTANTS_H
+#define CONSTANTS_H
+
+/*
+  Konstanter för olika aspekter av spelet. Dessa borde läsas från en fil.
+
+  (inline använd för att slippa lägga definitionen av konstanterna i en cc-fil. Ej en del av
+  kursen!)
+ */
+inline int const WIDTH  { 19 };
+inline int const HEIGHT { 22 };
+inline int TILE_SIZE { 20 };
+
+inline int const SCREEN_WIDTH  { WIDTH  * (TILE_SIZE + 1) };
+inline int const SCREEN_HEIGHT { HEIGHT * (TILE_SIZE + 1) };
+inline int const FPS { 60 };
+
+#endif
diff --git a/Uppgift-3-Spel/full_game/Code/entity.cc b/Uppgift-3-Spel/full_game/Code/entity.cc
new file mode 100644
index 0000000..65e143c
--- /dev/null
+++ b/Uppgift-3-Spel/full_game/Code/entity.cc
@@ -0,0 +1,38 @@
+#include "entity.h"
+
+#include "constants.h"
+
+Entity::Entity(sf::Vector2f const& start_position, Grid& grid, int speed, sf::Color const& color)
+    : current_target { start_position },
+      previous_target {},
+      current_direction {},
+      grid { grid },
+      speed { speed }
+{
+    setPosition(start_position);
+    setFillColor(color);
+}
+
+void Entity::update()
+{
+    if (at_target_position())
+    {
+        sf::Vector2f tmp { current_target };
+        select_new_target(current_target, current_direction);
+        previous_target = tmp;
+    }
+    move_forward();
+
+    time_passed += 1.0 / FPS;
+}
+
+bool Entity::at_target_position() const
+{
+    return abs(getPosition().x - current_target.x) < 0.1 and
+           abs(getPosition().y - current_target.y) < 0.1;
+}
+
+void Entity::move_forward()
+{
+    move(static_cast<sf::Vector2f>(current_direction * speed));
+}
diff --git a/Uppgift-3-Spel/full_game/Code/entity.h b/Uppgift-3-Spel/full_game/Code/entity.h
new file mode 100644
index 0000000..0824a6e
--- /dev/null
+++ b/Uppgift-3-Spel/full_game/Code/entity.h
@@ -0,0 +1,52 @@
+#ifndef ENTITY_H
+#define ENTITY_H
+
+#include <SFML/Graphics.hpp>
+#include <cmath>
+
+#include "grid.h"
+
+/*
+  Typdeklaration för att representera en position i kartan. Går i diskreta steg där varje steg representerar
+  en ruta.
+ */
+using Point = sf::Vector2i;
+
+/*
+  Basklass som representerar alla ritbara rörliga objekt i spelet. Har härledda klasser för pacman och spöken. 
+ */
+class Entity : public sf::ConvexShape
+{
+public:
+    Entity(sf::Vector2f const& start_position, Grid& grid, int speed, sf::Color const& color);
+    virtual ~Entity() = default;
+
+    /*
+      Uppdaterar objektets position. Varje Entity väljer en position en ruta framåt eller bakåt i x-
+      eller y-led och flyttar sig sedan med en jämn hastighet dit. När den når den rutan väljer den
+      en ny ruta och börjar om. Sättet den väljer en ruta sker med select_new_target() och
+      implementeras av den härledda klassen.
+     */
+    virtual void update();
+
+protected:
+    bool at_target_position() const;
+    virtual void move_forward();
+    
+    /*
+      Uppdaterar current_target till en ny position. Ska vara en ruta horisontellt eller vertikalt
+      bort från nuvarande position.
+     */
+    virtual void select_new_target(sf::Vector2f& current_target,
+                                   sf::Vector2i& current_direction) const = 0;
+
+    sf::Vector2f current_target;
+    sf::Vector2f previous_target;
+    sf::Vector2i current_direction;
+    Grid& grid;
+    int speed;
+
+    float time_passed {};
+};
+
+#endif
diff --git a/Uppgift-3-Spel/full_game/Code/game.cc b/Uppgift-3-Spel/full_game/Code/game.cc
new file mode 100644
index 0000000..f42e556
--- /dev/null
+++ b/Uppgift-3-Spel/full_game/Code/game.cc
@@ -0,0 +1,90 @@
+#include "game.h"
+
+#include "ghost.h"
+
+Game::Game()
+    : grid{"map.txt"},
+      pacman {{200, 340}, grid},
+      ghosts {},
+      window {sf::VideoMode {static_cast<unsigned>(SCREEN_WIDTH), static_cast<unsigned>(SCREEN_HEIGHT)}, "Pacman" }
+{
+    // Lägger till tre dynamiskt allokerade spöken i en vektor.
+    // Ett spökes konstruktor tar argumenten (pacman, startposition, scatterposition, + speciella argument). 
+    ghosts.emplace_back(sf::Vector2f{360,  40}, grid, new Blinky{pacman, Point{}, Point{WIDTH, 0}});
+    ghosts.emplace_back(sf::Vector2f{40 ,  40}, grid, new Pinky {pacman, Point{}, Point{0, 0}});
+    ghosts.emplace_back(sf::Vector2f{360, 420}, grid, new Clyde{pacman, Point{}, Point{0, HEIGHT}, 8});
+    window.setFramerateLimit(FPS);
+}
+
+void Game::run()
+{
+    bool running {true};
+    while (running)
+    {
+        window.clear();
+            
+        sf::Event event;
+        while (window.pollEvent(event))
+        {
+            if (event.type == sf::Event::Closed)
+            {
+                window.close();
+                running = false;
+            }
+        }
+
+        update();
+        draw();
+
+        if (check_collision())
+        {
+            std::cout << "Du kolliderade med ett spöke..." << std::endl;
+            running = false;
+        }
+
+        if (grid.food_count() == 0)
+        {
+            std::cout << "Du åt upp all mat! Bra jobbat!!" << std::endl;
+            running = false;
+        }
+    }
+}
+
+void Game::update()
+{
+    pacman.update();
+    
+    for (Ghost_Wrapper & g : ghosts)
+    {
+        g.update();
+    }
+}
+
+bool Game::check_collision() const
+{
+    for (Ghost_Wrapper const& g : ghosts)
+    {
+        if (pacman.getGlobalBounds().intersects(g.getGlobalBounds()))
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+void Game::draw()
+{
+    grid.draw(window);
+    window.draw(pacman);
+    for (Ghost_Wrapper const& g : ghosts)
+    {
+        window.draw(g);
+    }
+    
+    window.display();      
+}
+
+int Game::get_score()
+{
+    return pacman.get_score();
+}
diff --git a/Uppgift-3-Spel/full_game/Code/game.h b/Uppgift-3-Spel/full_game/Code/game.h
new file mode 100644
index 0000000..9f1cf21
--- /dev/null
+++ b/Uppgift-3-Spel/full_game/Code/game.h
@@ -0,0 +1,56 @@
+#ifndef GAME_H
+#define GAME_H
+
+#include "grid.h"
+#include "entity.h"
+#include "pacman.h"
+#include "ghost_wrapper.h"
+#include "constants.h"
+
+/*
+  Spelklassen har det yttersta ansvaret för spelet. Klassen sköter huvudloopen och deligerar ansvar till andra klasser. 
+ */
+class Game
+{
+public:
+    /*
+      Skapa en spelinstans och alla objekt i spelvärden. De är just nu hårdkodade till specifika
+      positioner. Detta borde läsas från kart-filen på ett snyggt sätt.
+    */
+    Game();
+       
+    /*
+      Huvudloopen i spelet. Det är här allt utgår ifrån. Hanterar användarindata, deligerar till andra
+      funktioner för att uppdatera spellogik och rendera till fönster. Gör också checkar för om spelet
+      är slut.
+    */
+    void run();
+
+    /*
+      Uppdatera spellogik. tex flytta pacman och alla spöken.
+    */
+    void update();
+    
+    /*
+      Kolla om pacman har kolliderat med någon av spökena.
+    */
+    bool check_collision() const;
+
+    /*
+      Rendera alla objekt i spelfönstret.
+    */
+    void draw();
+    
+    /*
+      Beräkna antal poäng spelaren har samlat på sig just nu.
+     */
+    int get_score();
+
+private:
+    Grid grid;
+    Pacman pacman;
+    std::vector<Ghost_Wrapper> ghosts;
+    sf::RenderWindow window;
+};
+
+#endif
diff --git a/Uppgift-3-Spel/full_game/Code/ghost_wrapper.cc b/Uppgift-3-Spel/full_game/Code/ghost_wrapper.cc
new file mode 100644
index 0000000..9ceb1ec
--- /dev/null
+++ b/Uppgift-3-Spel/full_game/Code/ghost_wrapper.cc
@@ -0,0 +1,108 @@
+#include "ghost_wrapper.h"
+
+#include <cmath>
+#include <algorithm>
+
+#include "constants.h"
+
+Ghost_Wrapper::Ghost_Wrapper(sf::Vector2f const& start_position, Grid& grid, Ghost* ghost)
+    : Entity {start_position, grid, 1, get_sfml_color(ghost)}, ghost {ghost}
+{
+    setPointCount(7);
+    
+    // Plockar fram ett antal punkter runt en cirkel för att skapa den ikoniska pacman-formen.
+    float radius { static_cast<float>(TILE_SIZE) / 2 };
+    int no_points { 5 };
+    for (int i {}; i < no_points; ++i)
+    {
+        setPoint(i, sf::Vector2f{ std::cos(3.14f / (no_points - 1) * i) * radius,
+                                  -std::sin(3.14f / (no_points - 1) * i) * radius });
+    }
+    setPoint(5, {-radius, radius});
+    setPoint(6, { radius, radius});
+    
+}
+
+void Ghost_Wrapper::update()
+{
+    if ((chase_mode && time_passed > 10) or
+        (!chase_mode && time_passed > 5))
+    {
+        chase_mode = !chase_mode;
+        time_passed = 0;
+        
+        current_direction = -current_direction;
+        std::swap(current_target, previous_target);
+    }
+
+    Entity::update();
+}
+
+// Ghost AI genomgång: https://gameinternals.com/understanding-pac-man-ghost-behavior
+void Ghost_Wrapper::select_new_target(sf::Vector2f& current_target,
+                              sf::Vector2i& current_direction) const
+{
+    sf::Vector2i curr { to_grid_pos(current_target) };
+    sf::Vector2i goal {};
+
+    // Plocka fram den nya 'goal'-punkten. Detta är olika för alla spöken.
+    ghost->set_position(to_grid_pos(getPosition()));
+    if (chase_mode)
+    {
+        goal = ghost->get_chase_point();
+    }
+    else
+    {
+        goal = ghost ->get_scatter_point();
+    }
+
+    // Hitta alla punkter precis brevid spöket. Detta är de möjliga nästa destinationerna.
+    std::vector<sf::Vector2i> potential_points { {curr.x + 1, curr.y}, {curr.x - 1, curr.y},
+                                                 {curr.x, curr.y + 1}, {curr.x, curr.y - 1} };
+
+    // Sortera punkterna så att punkten närmast 'goal'-punkten är först.
+    std::sort(potential_points.begin(), potential_points.end(),
+              [&goal](sf::Vector2i const& p1, sf::Vector2i const& p2)
+              {
+                  double p1_dist { pow(p1.x - goal.x, 2) + pow(p1.y - goal.y, 2) };
+                  double p2_dist { pow(p2.x - goal.x, 2) + pow(p2.y - goal.y, 2) };
+                  return p1_dist < p2_dist;
+              });
+
+    // Hitta den första punkten som inte är en vägg, eller positionen som spöket precis var på.
+    sf::Vector2i best_point = *std::find_if(potential_points.begin(), potential_points.end(),
+                                            [this](sf::Vector2i const& p)
+                                            {
+                                                return not grid.wall_at(p) and p != to_grid_pos(previous_target); 
+                                            });
+
+    // Uppdatera spökets riktningsvariabel. Kollar om spöket står stilla för att undvika division med noll. 
+    sf::Vector2f new_direction = (to_world_pos(best_point) - current_target);
+    float length = sqrt( (new_direction.x * new_direction.x) +
+                         (new_direction.y * new_direction.y));
+    if (length != 0)
+    {
+        current_target = to_world_pos(best_point);
+        current_direction = static_cast<sf::Vector2i>(new_direction / length);
+    }
+    else
+    {
+        current_direction = {};
+    }
+}
+
+sf::Color Ghost_Wrapper::get_sfml_color(Ghost* ghost) const
+{
+    std::string color {ghost->get_color()};
+    if (color == "red"   ) return sf::Color::Red;
+    if (color == "green" ) return sf::Color::Green;
+    if (color == "blue"  ) return sf::Color::Blue;
+    if (color == "orange") return sf::Color{255,165,0};
+    if (color == "yellow") return sf::Color::Yellow;
+    if (color == "pink"  ) return sf::Color{255,105,180};
+    if (color == "purple") return sf::Color{128,0,128};
+    if (color == "brown" ) return sf::Color{139,69,19};
+    if (color == "gray"  ) return sf::Color{128,128,128};
+    if (color == "black" ) return sf::Color::Black;
+    return sf::Color::White;
+}
diff --git a/Uppgift-3-Spel/full_game/Code/ghost_wrapper.h b/Uppgift-3-Spel/full_game/Code/ghost_wrapper.h
new file mode 100644
index 0000000..5fc976d
--- /dev/null
+++ b/Uppgift-3-Spel/full_game/Code/ghost_wrapper.h
@@ -0,0 +1,52 @@
+#ifndef GHOST_WRAPPER_H
+#define GHOST_WRAPPER_H
+
+#include <SFML/Graphics.hpp>
+#include <memory>
+
+#include "entity.h"
+#include "grid.h"
+#include "YOUR_CODE_HERE/ghost.h"
+
+/*
+  En klass som äger ett objekt av den studentskapade datatypen "Ghost". Se detta som en klass som
+  lägger till grafikelement och sökalgoritm till klasserna som studenten skapat.
+
+ */
+class Ghost_Wrapper : public Entity
+{
+public:
+    Ghost_Wrapper(sf::Vector2f const& start_position, Grid& grid, Ghost* ghost);
+    
+    /*
+      Utökar Entitys update med funktionallitet för att byta mellan chase och scatter.
+
+      Anropar sedan Entitys update. Kolla där för detaljer.
+     */
+    void update() override;
+
+protected:
+
+    /*
+      Väljer en ny punkt för spöket att gå till. Detta görs när spöket har nått sitt förra mål.
+
+      Notera att detta inte är samma sak som det studenten ska implementera. Detta är ruta för ruta
+      och använder sig av studentkod, men de är inte samma.
+     */
+    void select_new_target(sf::Vector2f& current_target,
+                           sf::Vector2i& current_direction) const override;
+
+private:
+
+    /*
+      Konverterar den färg-strängen som spöket sparar till en faktiskt sfml-färg.
+
+      Följ mönstret för att lägga till fler färger.
+     */
+    sf::Color get_sfml_color(Ghost* ghost) const;
+
+    std::unique_ptr<Ghost> ghost;
+    bool chase_mode {true};
+};
+
+#endif
diff --git a/Uppgift-3-Spel/full_game/Code/given.h b/Uppgift-3-Spel/full_game/Code/given.h
new file mode 100644
index 0000000..b97738d
--- /dev/null
+++ b/Uppgift-3-Spel/full_game/Code/given.h
@@ -0,0 +1,6 @@
+/*
+  Detta är en liten wrapper för att studentkoden inte ska behöva ändras för den läggs in i spelet.
+  Utan detta skulle man behöva ändra vilka filer som inkluderas i studentkoden.
+ */
+#include "constants.h"
+#include "pacman.h"
diff --git a/Uppgift-3-Spel/full_game/Code/grid.cc b/Uppgift-3-Spel/full_game/Code/grid.cc
new file mode 100644
index 0000000..d067166
--- /dev/null
+++ b/Uppgift-3-Spel/full_game/Code/grid.cc
@@ -0,0 +1,135 @@
+#include "grid.h"
+
+#include <fstream>
+#include <deque>
+#include <algorithm>
+
+#include "constants.h"
+
+std::istream& operator>>(std::istream& is, Row& row)
+{
+    std::string line {};
+    getline(is, line);
+    std::istringstream iss {line};
+
+    if (line.size() != WIDTH)
+    {
+        is.setstate(std::ios::failbit);
+    }
+
+    row.clear();
+    
+    char c {};
+    while(iss >> c)
+    {
+        row.push_back(c);
+    }
+    
+    if ( row.size() != 0 and row.size() != WIDTH )
+    {
+        throw std::runtime_error{"wrong width [" + std::to_string(row.size()) + "] of row. Expected " + std::to_string(WIDTH)};
+    }
+    return is;
+}
+
+sf::Vector2i to_grid_pos(sf::Vector2f const& pos)
+{
+    return { static_cast<int>((pos.x - TILE_SIZE) / TILE_SIZE),
+             static_cast<int>((pos.y - TILE_SIZE) / TILE_SIZE) };
+}
+
+sf::Vector2f to_world_pos(sf::Vector2i const& pos)
+{
+    return { static_cast<float>(pos.x * TILE_SIZE + TILE_SIZE),
+             static_cast<float>(pos.y * TILE_SIZE + TILE_SIZE) };
+}
+
+Grid::Grid(std::string const& map_file)
+{
+    std::ifstream ifs {map_file};
+    
+    Row row {};
+    while (ifs >> row)
+    {
+        rows.push_back(row);
+    }
+
+    if (rows.size() != HEIGHT)
+    {
+        throw std::runtime_error{"wrong height [" + std::to_string(rows.size()) + "] of map. Expected " + std::to_string(HEIGHT)};
+    }
+}
+
+void Grid::draw(sf::RenderWindow& window) const
+{
+    // Skapa en rektangel med rätt storlek och färg. Flyttas till olika positioner och ritas ut
+    // en gång för varje vägg.
+    sf::RectangleShape box {{TILE_SIZE / 1.5f, TILE_SIZE / 1.5f}};
+    box.setFillColor(sf::Color::Blue);
+    box.setOrigin(box.getSize().x / 2,box.getSize().y / 2);
+
+    // Skapa en cirkel med rätt storlek och färg. Flyttas till olika positioner och ritas ut en gång
+    // för varje mat.
+    sf::CircleShape food {2};
+    food.setFillColor(sf::Color::White);
+    food.setOrigin(food.getRadius(), food.getRadius());
+    
+    for (unsigned i {}; i < rows.size(); ++i)
+    {
+        for (unsigned j {}; j < rows[i].size(); ++j)
+        {
+            switch (rows[i][j])
+            {
+            case 'w':
+                box.setPosition((j + 1) * TILE_SIZE, (i + 1) * TILE_SIZE);
+                window.draw(box);
+                break;
+            case 'f':
+                food.setPosition((j + 1) * TILE_SIZE, (i + 1) * TILE_SIZE);
+                window.draw(food);
+                break;
+            default:
+                break;
+            }
+        }
+    }
+}
+
+bool Grid::wall_at(sf::Vector2i const& grid_pos) const
+{
+    if (grid_pos.x < 0 or grid_pos.x >= static_cast<int>(rows[0].size()) or
+        grid_pos.y < 0 or grid_pos.y >= static_cast<int>(rows.size()) )
+    {
+        return true;
+    }
+    
+    return rows[grid_pos.y][grid_pos.x] == 'w';
+}
+
+bool Grid::eat_food(sf::Vector2i const& grid_pos)
+{
+    if (rows[grid_pos.y][grid_pos.x] == 'f')
+    {
+        rows[grid_pos.y][grid_pos.x] = 'e';
+        return true;
+    }
+    return false;
+}
+
+
+int Grid::food_count() const
+{
+    int count {};
+
+    for (unsigned i {}; i < rows.size(); ++i)
+    {
+        for (unsigned j {}; j < rows[i].size(); ++j)
+        {
+            if (rows[i][j] == 'f')
+            {
+                ++count;
+            }
+        }
+    }
+    return count;
+}
diff --git a/Uppgift-3-Spel/full_game/Code/grid.h b/Uppgift-3-Spel/full_game/Code/grid.h
new file mode 100644
index 0000000..6005b99
--- /dev/null
+++ b/Uppgift-3-Spel/full_game/Code/grid.h
@@ -0,0 +1,59 @@
+#ifndef GRID_H
+#define GRID_H
+
+#include <SFML/Graphics.hpp>
+#include <iostream>
+#include <sstream>
+#include <string>
+
+/*
+  Datatyp för att representera en rad i rutnätet som är kartan.
+ */
+using Row = std::vector<char>;
+std::istream& operator>>(std::istream& is, Row& row);
+
+/*
+  Hjälpfunktioner för att konvertera mellan två olika coordinatsystem.
+
+  'grid' är ett coordinatsystem där varje ruta på spelplanen är en coordinat.
+  'world' är ett coordinatsystem där varje pixel på skärmen är en coordinat.
+ */
+sf::Vector2i to_grid_pos(sf::Vector2f const& pos);
+sf::Vector2f to_world_pos(sf::Vector2i const& pos);
+
+/*
+  Klass som representerar hela kartan. Dvs håller koll på alla positioner för väggar och mat på
+  kartan.
+ */
+class Grid
+{
+public:
+
+    Grid(std::string const& map_file);
+
+    /*
+      Rendera alla väggar och all mat.
+    */
+    void draw(sf::RenderWindow& window) const;
+
+    /*
+      Ger sant om det är en vägg på given position. Notera att positionen måste anges i
+      'grid'-systemet.
+    */
+    bool wall_at(sf::Vector2i const& grid_pos) const;
+
+    /*
+      Ger sant om det var en mat på given position. Plockar då också bort maten. Notera att
+      positionen måste anges i 'grid'-systemet.
+
+      Om det inte var en mat på positionen returneras 'false' och inget mer händer. 
+    */
+    bool eat_food(sf::Vector2i const& grid_pos);
+
+    int food_count() const;
+
+private:
+    std::vector<Row> rows {};
+};
+
+#endif
diff --git a/Uppgift-3-Spel/full_game/Code/pacman.cc b/Uppgift-3-Spel/full_game/Code/pacman.cc
new file mode 100644
index 0000000..4134a8e
--- /dev/null
+++ b/Uppgift-3-Spel/full_game/Code/pacman.cc
@@ -0,0 +1,92 @@
+#include "pacman.h"
+
+#include <cmath>
+
+#include "constants.h"
+
+Pacman::Pacman(sf::Vector2f const& start_position, Grid& grid)
+    : Entity{start_position, grid, 2, sf::Color::Yellow},
+      next_direction {}, score {}
+{
+    int no_points { 8 };
+    float radius { 10 };
+    
+    setPointCount(no_points);
+    
+    for (int i {}; i < no_points; ++i)
+    {
+        setPoint(i, sf::Vector2f{ std::cos(6.28f / (no_points) * i) * radius,
+                                  std::sin(6.28f / (no_points) * i) * radius });
+    }
+}
+
+void Pacman::update()
+{
+    handle_input();
+
+    if (next_direction == -current_direction)
+    {
+        current_direction = next_direction;
+        std::swap(current_target, previous_target);
+    }
+
+    if (grid.eat_food(to_grid_pos(getPosition())))
+    {
+        score += 10;
+    }
+
+    Entity::update();
+}
+
+Point Pacman::get_position() const
+{
+    return { static_cast<int>((getPosition().x - TILE_SIZE) / TILE_SIZE),
+             static_cast<int>((getPosition().y - TILE_SIZE) / TILE_SIZE) };
+}
+
+Point Pacman::get_direction() const
+{
+    return { current_direction.x, current_direction.y };
+}
+
+void Pacman::select_new_target(sf::Vector2f& current_target,
+                               sf::Vector2i& current_direction) const
+{
+    // Plockar fram potentiella nästa punkter. Det är antingen en position framåt i spelarens
+    // riktning, eller stå stilla.
+    std::vector<sf::Vector2i> candidates { next_direction, current_direction };
+    
+    // Stega igenom listan med potentiella punkter och plocka den första som inte är en vägg.
+    for (sf::Vector2i const& candidate : candidates)
+    {
+        sf::Vector2f new_target { current_target + static_cast<sf::Vector2f>(candidate * static_cast<int>(TILE_SIZE)) };
+        if ( not grid.wall_at(to_grid_pos(new_target)) )
+        {
+            current_direction = candidate;
+            current_target = new_target;
+            return;
+        }
+    }
+    current_direction = {};
+}
+
+void Pacman::handle_input()
+{
+    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
+    {
+        next_direction = {0, -1};
+    }
+    else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
+    {
+        next_direction = {0, 1};
+    }
+    else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
+    {
+        next_direction = {-1, 0};
+    }
+    else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
+    {
+        next_direction = {1, 0};
+    }
+}
+
diff --git a/Uppgift-3-Spel/full_game/Code/pacman.h b/Uppgift-3-Spel/full_game/Code/pacman.h
new file mode 100644
index 0000000..325b1b4
--- /dev/null
+++ b/Uppgift-3-Spel/full_game/Code/pacman.h
@@ -0,0 +1,52 @@
+#ifndef PACMAN_H
+#define PACMAN_H
+
+#include <SFML/Graphics.hpp>
+
+#include "entity.h"
+#include "grid.h"
+
+/*
+  Pacmanklassen representerar spelarefiguren i spelet. Den innehåller funktionallitet för att flytta och rendera spelarefiguren. 
+
+  Är en specialicering av basklassen Entity.
+ */
+class Pacman : public Entity
+{
+public:
+    Pacman(sf::Vector2f const& start_position, Grid& grid);
+
+    /*
+      Uppdatera pacmans position och riktning.
+     */
+    void update() override;
+
+    /*
+      Hämta ut olika egenskaper från pacman.
+     */
+    unsigned get_score() const { return score; };
+    Point get_position()  const;
+    Point get_direction() const;
+
+protected:
+
+    /*
+      Använder användainmatning för att beräkna vilken nästa ruta spelare ska röra sig till är.
+     */
+    void select_new_target(sf::Vector2f& current_target,
+                           sf::Vector2i& current_direction) const override;
+    
+private:
+
+    /*
+      Kollar vilka knappar som är nedtryckta och uppdaterar variabeln next_direction baserat på det.
+
+      Ändra i denna om du vill ha andra knappar som styr spelaren.
+     */
+    void handle_input();
+
+    sf::Vector2i next_direction;
+    unsigned score;
+};
+
+#endif
diff --git a/Uppgift-3-Spel/full_game/Makefile b/Uppgift-3-Spel/full_game/Makefile
new file mode 100644
index 0000000..dad0d52
--- /dev/null
+++ b/Uppgift-3-Spel/full_game/Makefile
@@ -0,0 +1,15 @@
+FLAGS = -std=c++17 -Wall -Wextra -Wpedantic -Weffc++ -g -I. -ICode -IYOUR_CODE_HERE
+LIB = -lsfml-graphics -lsfml-system -lsfml-window
+
+pacman: main.cc game.o entity.o pacman.o ghost_wrapper.o grid.o student_code.o
+	g++ $(FLAGS) -o pacman main.cc game.o entity.o pacman.o ghost_wrapper.o grid.o student_code.o $(LIB)
+
+student_code.o: $(shell find YOUR_CODE_HERE -type f)
+	g++ -o student_code.o $(FLAGS) -c YOUR_CODE_HERE/*.cc
+
+%.o: Code/%.cc Code/%.h
+	g++ $(FLAGS) -o $@ -c $<
+
+.PHONY: clean
+clean:
+	rm -f *.o ./pacman
diff --git a/Uppgift-3-Spel/full_game/README.md b/Uppgift-3-Spel/full_game/README.md
new file mode 100644
index 0000000..480b754
--- /dev/null
+++ b/Uppgift-3-Spel/full_game/README.md
@@ -0,0 +1,14 @@
+Steg för att spela pacman med dina egna spöken.
+
+1. Lägg en (1) headerfil med kod för alla spöken i mappen YOUR_CODE_HERE. Den ska heta ghost.h.
+2. Lägg en (1) implemenationsfil med kod för alla spöken i mappen YOUR_CODE_HERE. 
+3. Flytta *inte* med huvudprogrammet eller de givna filerna till mappen.
+4. Stå i mappen med filen som heter Makefile och skriv 'make' i terminalen.
+5. Kör programmet med './pacman'.
+6. Fly från dina spöken.
+
+Om du har problem med att kompilera koden, se till att alla klasser och funktioner heter som angivet
+i labbinstruktionen. Det går också att gå in i spelkoden och kolla vad som väntas. Det är primärt
+filerna Code/ghost_wrapper.h och Code/game.h som är relevanta. 
+
+Prata med en assistent om ni inte får det att kompilera.
diff --git a/Uppgift-3-Spel/full_game/main.cc b/Uppgift-3-Spel/full_game/main.cc
new file mode 100644
index 0000000..06a9467
--- /dev/null
+++ b/Uppgift-3-Spel/full_game/main.cc
@@ -0,0 +1,20 @@
+
+#include <SFML/Graphics.hpp>
+#include <iostream>
+
+#include "game.h" 
+
+using namespace std;
+
+int main()
+{
+    cout << "Välkommen till Pacman\nTryck 'Enter' för att starta";
+    cin.get();
+
+    Game game {};
+    game.run();
+
+    cout << "Du fick " << game.get_score() << " poäng" << std::endl;
+    cout << "Tryck 'Enter' för att avsluta" << std::endl;
+    cin.get();
+}
diff --git a/Uppgift-3-Spel/full_game/map.txt b/Uppgift-3-Spel/full_game/map.txt
new file mode 100644
index 0000000..f757795
--- /dev/null
+++ b/Uppgift-3-Spel/full_game/map.txt
@@ -0,0 +1,22 @@
+wwwwwwwwwwwwwwwwwww
+wffffffffwffffffffw
+wfwwfwwwfwfwwwfwwfw
+wfwwfwwwfwfwwwfwwfw
+wfffffffffffffffffw
+wfwwfwfwwwwwfwfwwfw
+wffffwfffwfffwffffw
+wwwwfwwwewewwwfwwww
+wwwwfweeeeeeewfwwww
+wwwwfwewwwwwewfwwww
+eeeefeewwwwweefeeee
+wwwwfwewwwwwewfwwww
+wwwwfweeeeeeewfwwww
+wwwwfwewwwwwewfwwww
+wffffffffwffffffffw
+wfwwfwwwfwfwwwfwwfw
+wffwfffffffffwfwffw
+wwfwfwfwwwwwfwfwfww
+wffffwfffwffffffffw
+wfwwwwwwfwfwwwwwwfw
+wfffffffffffffffffw
+wwwwwwwwwwwwwwwwwww
diff --git a/Uppgift-3-Spel/ghost.h b/Uppgift-3-Spel/ghost.h
new file mode 100644
index 0000000..74e3750
--- /dev/null
+++ b/Uppgift-3-Spel/ghost.h
@@ -0,0 +1,74 @@
+#ifndef GHOST_H 
+#define GHOST_H
+
+#include "given.h"
+#include "string"
+using namespace std;
+
+class Ghost
+{
+public:
+    Ghost(Point const& start_position, std::string const& color);
+    virtual ~Ghost() = default;
+    virtual Point get_scatter_point(const Point& pacmanPosition) const = 0;
+    virtual Point get_chase_point(const Point& pacmanPosition, const Point& pacmanDirection) = 0;
+    virtual void set_position(const Point& new_position);
+    virtual Point get_position();
+    virtual std::string get_color() const = 0;
+    // virtual Point get_target_position() const = 0;
+
+    virtual void set_blinky_position(const Point& new_position)
+    {
+        blinkyPosition.x = new_position.x;
+        blinkyPosition.y = new_position.y;
+    }
+    virtual void set_pinky_position(const Point& new_position)
+    {
+        pinkyPosition.x = new_position.x;
+        pinkyPosition.y = new_position.y;
+    }
+protected:
+    Point position;
+    std::string colorName;
+    Point blinkyPosition;
+    Point pinkyPosition;
+};
+
+class Clyde
+{
+public:
+    Clyde(std::string const &color, Point const &start_pos);
+    void set_pos(const Point &new_pos);
+    Point get_scatter(const Point &pos_pacman);
+    Point get_chase(const Point &pos_pacman, const Point &dir_pacman);
+    Point get_pos();
+    std::string get_color()const;
+};
+
+class Pinky
+{
+public:
+    Pinky(std::string const &color, Point const &start_pos);
+    void set_pos(const Point &new_pos);
+    Point get_scatter(const Point &pos_pacman);
+    Point get_chase(const Point &pos_pacman, const Point &dir_pacman);
+    Point get_pos();
+    std::string get_color()const;
+};
+
+
+
+class Blinky
+{
+public:
+    bool angry();
+    bool anger_activated(bool state);
+    Blinky(std::string const &color, Point const &start_pos);
+    void set_pos(const Point &new_pos);
+    Point get_scatter(const Point &pos_pacman);
+    Point get_chase(const Point &pos_pacman, const Point &dir_pacman);
+    Point get_pos();
+    std::string get_color()const;
+};
+
+#endif
\ No newline at end of file
diff --git a/Uppgift-3-Spel/given.cc b/Uppgift-3-Spel/given.cc
new file mode 100644
index 0000000..154bfe8
--- /dev/null
+++ b/Uppgift-3-Spel/given.cc
@@ -0,0 +1,46 @@
+#include "given.h"
+
+int WIDTH = 19;
+int HEIGHT = 22;
+
+bool operator==(Point const& lhs, Point const& rhs)
+{
+    return lhs.x == rhs.x && lhs.y == rhs.y;
+}
+
+std::istream& operator>>(std::istream& is, Point& rhs)
+{
+    return is >> rhs.x >> rhs.y;
+}
+
+Pacman::Pacman()
+    : pos {}, dir {1,0}
+{}
+
+Point Pacman::get_position() const
+{
+    return pos;
+}
+
+void Pacman::set_position(Point const& p)
+{
+    if (p.x > WIDTH or p.x < 0 or p.y > HEIGHT or p.y < 0)
+    {
+        throw std::runtime_error("position outside valid range");
+    }
+    pos = p;
+}
+
+Point Pacman::get_direction() const
+{
+    return dir;
+}
+
+void Pacman::set_direction(Point const& p)
+{
+    if (p.x > 1 or p.x < -1 or p.y > 1 or p.y < -1 or abs(p.x + p.y) != 1)
+    {
+        throw std::runtime_error("direction outside valid range");
+    }
+    dir = p;
+}
diff --git a/Uppgift-3-Spel/given.h b/Uppgift-3-Spel/given.h
new file mode 100644
index 0000000..2999a6d
--- /dev/null
+++ b/Uppgift-3-Spel/given.h
@@ -0,0 +1,62 @@
+// TODO: skydd f�r dubbel inkludering
+
+/*
+  I denna fil finns ett utval av kod fr�n det dina kollegor skrivit till ert pacman-projekt. Det �r
+  precis det som du beh�ver f�r att skriva din del av koden.
+
+  Tips: Du f�r ut�ka denna fil med saker som du beh�ver f�r att ditt program ska kompilera. Det �r
+  �ven okej att ut�ka Point med fler operatorer om det skulle beh�vas.
+ */
+
+
+#include <stdexcept>
+#include <iostream>
+
+
+/*
+  Globala variabler f�r storlek p� spelplanen.
+
+  Din kollega som skrev detta �r medveten om att globala variabler �r d�ligt och borde undvikas, men
+  har inte haft tid att �tg�rda det. I den slutgiltiga versionen av koden borde dessa s�klart l�sas
+  fr�n en fil med konfigurationsdata.
+ */
+extern int WIDTH;
+extern int HEIGHT;
+
+
+/*
+  Ett aggregat som anv�nd f�r att representera punkter och riktninar p� spelplanen.
+  Aggregatet har ocks� hj�lpsamma operatorer som kan underl�tta din implementation.
+
+ */
+struct Point
+{
+    int x;
+    int y;
+};
+bool operator==(Point const& lhs, Point const& rhs);
+std::istream& operator>>(std::istream& is, Point& rhs);
+
+
+/*
+  En klass f�r att representera spelarfiguren. Detta �r en nedskalad version j�mf�rt med det som
+  kollegan skrev till spelet. Notera att din kod inte beh�ver �ndras om man skulle g� fr�n denna
+  implementaion till den faktiska implementationen.
+ */
+class Pacman
+{
+public:
+
+    Pacman();
+    
+    Point get_position() const;
+    void set_position(Point const& p);
+
+    Point get_direction() const;
+    void set_direction(Point const& p);
+
+private:
+    
+    Point pos {};
+    Point dir {};
+};
diff --git a/Uppgift-3-Spel/main.cc b/Uppgift-3-Spel/main.cc
new file mode 100644
index 0000000..6f829e5
--- /dev/null
+++ b/Uppgift-3-Spel/main.cc
@@ -0,0 +1,112 @@
+#include "ghost.h"
+#include <string>
+#include <iostream>
+#include <iomanip>
+#include <sstream>
+
+using namespace std;
+
+/*
+  Ledning och Tips:
+
+  - Modifiera stukturen till en header-fil och en implementationsfil
+  - Ut�ka 'run()' och 'draw_map()' med �vrig funktionalitet.
+  - L�gg alla sp�ken i en l�mplig beh�llare som en datamedlem.
+  - Bryt ut stora kodblock till egna funktioner.
+  - Anv�nd hj�lpfunktioner f�r att undvika duplicering av kod.
+  - T�nk p� att varje funktion inte borde vara l�ngre �n 25 rader.
+ */
+
+class Ghost_Tester
+{
+
+public:
+
+    Ghost_Tester()
+        : pacman {}
+    {
+    }
+
+    void run()
+    {
+        while(true)
+        {
+            draw_map();
+            cout << "> ";
+
+            string line {};
+            getline(cin, line);
+            istringstream iss {line};
+        
+            string command {};
+            iss >> command;
+
+            if (command == "pos")
+            {
+                Point new_pos {};
+                iss >> new_pos.x >> new_pos.y;
+                pacman.set_position(new_pos);
+            }
+            else if (command == "dir")
+            {
+            }
+            else if (command == "quit")
+            {
+                break;
+            }
+        }
+    }
+    
+private:
+
+    /*
+      En hj�lpfunktion som avg�r vilka tv� tecken som ska ritas ut f�r en given position p�
+      spelplanen.
+     */
+    string to_draw(Point const& curr_pos)
+    {
+        string to_draw{"  "};
+
+        if (pacman.get_position() == curr_pos)
+        {
+            to_draw[1] = '@';
+        }
+
+        return to_draw;
+    }
+    
+    /*
+      En hj�lpfunktion f�r att rita ut spelplanen f�r testprogrammet.
+      
+      Itererar �ver varje rad och column i kartan. Index f�r raderna �r flippade f�r att placera
+      y = 0 l�ngst ned.
+      
+      Varje punkt i kartan ritas som tv� tecken eftersom ett tecken i terminalen �r ca dubbelt s�
+      h�gt som det �r brett.
+    */
+    void draw_map()
+    {
+        cout << "+" << setfill('-') << setw(WIDTH * 2) << "-" << "+\n";
+
+        for (int y {HEIGHT - 1}; y >= 0; --y) 
+        {
+            cout << "|";
+            for (int x {}; x < WIDTH; ++x) 
+            {
+                cout << to_draw( Point{x,y} );
+            }
+            cout << "|\n";
+        }
+    
+        cout << "+" << setfill('-') << setw(WIDTH * 2) << "-" << "+" << endl;
+    }
+
+    Pacman pacman;
+};
+
+int main()
+{
+    Ghost_Tester gt {};
+    gt.run();
+    return 0;
+}
diff --git a/ghost.h b/ghost.h
deleted file mode 100644
index 7256769..0000000
--- a/ghost.h
+++ /dev/null
@@ -1,76 +0,0 @@
-
-#infdef ghost.h 
-#define ghost.h
-
-#include "given.h"
-#include "string"
-using namespace std;
-class Ghost
-{
-public:
-Clyde(std::string const &color, Point const &start_pos);
-virtual void set_pos(const Point &new_pos);
-virtual Point get_scatter(const Point &pos_pacman) = 0;
-virtual Point get_chase(const Point &pos_pacman, const Point &dir_pacman) = 0;
-virtual Point get_pos();
-virtual std::string get_color()const = 0;
-virtual ~Ghost() = default;
-
-
-
-private:
-std::string color_index
-Point position; 
-
-};
-
-
-
-class Clyde
-{
-    public:
-Clyde(std::string const &color, Point const &start_pos);
-void set_pos(const Point &new_pos);
-Point get_scatter(const Point &pos_pacman);
-Point get_chase(const Point &pos_pacman, const Point &dir_pacman);
-Point get_pos();
-std::string get_color()const;
-
-
-
-};
-
-
-
-class Pinky
-{
-    public:
-Pinky(std::string const &color, Point const &start_pos);
-void set_pos(const Point &new_pos);
-Point get_scatter(const Point &pos_pacman);
-Point get_chase(const Point &pos_pacman, const Point &dir_pacman);
-Point get_pos();
-std::string get_color()const;
-
-
-
-};
-
-
-
-class Blinky
-{
-    public:
-Bool angry();
-anger_activated(bool state);
-Blinky(std::string const &color, Point const &start_pos);
-void set_pos(const Point &new_pos);
-Point get_scatter(const Point &pos_pacman);
-Point get_chase(const Point &pos_pacman, const Point &dir_pacman);
-Point get_pos();
-std::string get_color()const;
-
-
-
-};
-#endif
\ No newline at end of file
-- 
GitLab