Go back to Richel Bilderbeek's homepage.

Go back to Richel Bilderbeek's C++ page.

 

 

 

 

 

(C++) GameMaziak

 

Maziak is a simple maze retro game (and a clone of the Sinclair ZX Spectrum/MSX game Maziak/Maziacs/Mazoggs), in which you have to find a maze's exit. But there are also enemies in the maze that can be beaten by a sword. There are also prisoners, that temporarily show the way to the exit upon freeing them.

 

 

 

 

 

Downloads

 

  1. View a screenshot of 'Maziak' (v.2.0)(png)
  2. View a screenshot of the 'Maziak' menu screen (v.2.0)(png)
  3. View a screenshot of the 'Maziak' instructions screen (v.2.0)(png)
  4. Download the 'Maziak' (png) sprites (v.2.0)(zip)
  5. Older: Maziak (VCL)

 

 

 

 

 

Maziak history

 

 

 

 

 

 

External links

 

Technical facts

 

Operating system(s) or programming environment(s)

IDE(s):

Project type:

C++ standard:

Compiler(s):

Libraries used:

 

 

 

 

 

Qt project file: ./GameMaziak/GameMaziakConsole.pro

 

include(../../ConsoleApplication.pri)

include(../../Libraries/Boost.pri)

include(../../Classes/CppAbout/CppAbout.pri)
include(../../Classes/CppFileIo/CppFileIo.pri)
include(../../Classes/CppHelp/CppHelp.pri)
include(../../Classes/CppMenuDialog/CppMenuDialog.pri)
include(../../Classes/CppRichelBilderbeekProgram/CppRichelBilderbeekProgram.pri)
include(../../Classes/CppTrace/CppTrace.pri)

#Specific, console
include(../../Classes/CppCanvas/CppCanvas.pri)
include(../../Classes/CppDotMatrix/CppDotMatrix.pri)
include(../../Classes/CppTextCanvas/CppTextCanvas.pri)
include(../../Games/GameMaziak/GameMaziakConsole.pri)

SOURCES += main.cpp

 

 

 

 

 

Qt project file: ./GameMaziak/GameMaziakDesktop.pro

 

include(../../DesktopApplication.pri)
include(../../Libraries/Apfloat.pri)
include(../../Libraries/Boost.pri)
include(../../Libraries/GeneralConsole.pri)
include(../../Libraries/GeneralDesktop.pri)

#Specific, console
include(../../Classes/CppCanvas/CppCanvas.pri)
include(../../Classes/CppContainer/CppContainer.pri)
include(../../Classes/CppDotMatrix/CppDotMatrix.pri)
include(../../Classes/CppGeometry/CppGeometry.pri)
include(../../Classes/CppPlane/CppPlane.pri)
include(../../Classes/CppRibiRegex/CppRibiRegex.pri)
include(../../Classes/CppTextCanvas/CppTextCanvas.pri)
include(../../Classes/CppWidget/CppWidget.pri)

#Specific, desktop
include(../../Classes/CppQtCanvas/CppQtCanvas.pri)
include(GameMaziakDesktop.pri)

SOURCES += qtmain.cpp

 

 

 

 

 

Qt project file: ./GameMaziak/GameMaziakWebsite.pro

 

include(../../DesktopApplication.pri)

include(../../Libraries/Boost.pri)

include(../../Classes/CppAbout/CppAbout.pri)
include(../../Classes/CppFileIo/CppFileIo.pri)
include(../../Classes/CppHelp/CppHelp.pri)
include(../../Classes/CppMenuDialog/CppMenuDialog.pri)
include(../../Classes/CppRichelBilderbeekProgram/CppRichelBilderbeekProgram.pri)
include(../../Classes/CppTrace/CppTrace.pri)

include(../../Classes/CppQtAboutDialog/CppQtAboutDialog.pri)
include(../../Classes/CppQtHideAndShowDialog/CppQtHideAndShowDialog.pri)

include(GameMaziakDesktop.pri)

SOURCES += qtmain.cpp

 

 

 

 

 

./GameMaziak/GameMaziakConsole.pri

 

INCLUDEPATH += \
    ../../Games/GameMaziak

SOURCES += \
    ../../Games/GameMaziak/maziakmenudialog.cpp \
    ../../Games/GameMaziak/maziakplayerdirection.cpp \
    ../../Games/GameMaziak/maziakplayermove.cpp \
    ../../Games/GameMaziak/maziakmazesquare.cpp \
    ../../Games/GameMaziak/maziakdifficulty.cpp \
    ../../Games/GameMaziak/maziakhelper.cpp \
    ../../Games/GameMaziak/maziakintmaze.cpp \
    ../../Games/GameMaziak/maziaksprites.cpp \
    ../../Games/GameMaziak/maziaksprite.cpp \
    ../../Games/GameMaziak/maziakmaze.cpp \
    ../../Games/GameMaziak/maziakdistancesmaze.cpp \
    ../../Games/GameMaziak/maziaksolutionmaze.cpp \
    ../../Games/GameMaziak/maziakmaindialog.cpp \
    ../../Games/GameMaziak/maziakkey.cpp \
    ../../Games/GameMaziak/maziakreceiver.cpp

HEADERS  += \
    ../../Games/GameMaziak/maziakmenudialog.h \
    ../../Games/GameMaziak/maziakplayerdirection.h \
    ../../Games/GameMaziak/maziakplayermove.h \
    ../../Games/GameMaziak/maziakmazesquare.h \
    ../../Games/GameMaziak/maziakdifficulty.h \
    ../../Games/GameMaziak/maziakhelper.h \
    ../../Games/GameMaziak/maziakintmaze.h \
    ../../Games/GameMaziak/maziakfwd.h \
    ../../Games/GameMaziak/maziaksprites.h \
    ../../Games/GameMaziak/maziaksprite.h \
    ../../Games/GameMaziak/maziakmaze.h \
    ../../Games/GameMaziak/maziakdistancesmaze.h \
    ../../Games/GameMaziak/maziaksolutionmaze.h \
    ../../Games/GameMaziak/maziakmaindialog.h \
    ../../Games/GameMaziak/maziakkey.h \
    ../../Games/GameMaziak/maziakreceiver.h

OTHER_FILES += \
    ../../Games/GameMaziak/Licence.txt

RESOURCES += \
    ../../Games/GameMaziak/GameMaziak.qrc

 

 

 

 

 

./GameMaziak/GameMaziakDesktop.pri

 

include(../../Games/GameMaziak/GameMaziakConsole.pri)

SOURCES += \
    ../../Games/GameMaziak/qtmaziakmenudialog2.cpp \
    ../../Games/GameMaziak/qtmaziakmaindialog.cpp \
    ../../Games/GameMaziak/qtmaziakinstructionsdialog.cpp \
    ../../Games/GameMaziak/qtmaziakgamewondialog.cpp \
    ../../Games/GameMaziak/qtmaziakgameoverdialog.cpp \
    ../../Games/GameMaziak/qtmaziakcanvas.cpp

HEADERS  += \
    ../../Games/GameMaziak/qtmaziakmenudialog2.h \
    ../../Games/GameMaziak/qtmaziakmaindialog.h \
    ../../Games/GameMaziak/qtmaziakinstructionsdialog.h \
    ../../Games/GameMaziak/qtmaziakgamewondialog.h \
    ../../Games/GameMaziak/qtmaziakgameoverdialog.h \
    ../../Games/GameMaziak/qtmaziakcanvas.h


FORMS += \
    ../../Games/GameMaziak/qtmaziakmenudialog2.ui \
    ../../Games/GameMaziak/qtmaziakmaindialog.ui \
    ../../Games/GameMaziak/qtmaziakinstructionsdialog.ui \
    ../../Games/GameMaziak/qtmaziakgamewondialog.ui \
    ../../Games/GameMaziak/qtmaziakgameoverdialog.ui

 

 

 

 

 

./GameMaziak/GameMaziakWebsite.pri

 

include(../../Games/GameMaziak/GameMaziakConsole.pri)

RESOURCES += \
    ../../Games/GameMaziak/GameMaziak.qrc

 

 

 

 

 

./GameMaziak/main.cpp

 

#include <iostream>

#include "maziakmenudialog.h"

int main(int argc, char * argv[])
{
  const std::vector<std::string> args { ribi::MenuDialog::ConvertArguments(argc,argv) };
  return ribi::maziak::MenuDialog().Execute(args);
}

 

 

 

 

 

./GameMaziak/maziakdifficulty.h

 

#ifndef MAZIAKDIFFICULTY_H
#define MAZIAKDIFFICULTY_H

namespace ribi {
namespace maziak {

enum class Difficulty { easy, medium, hard };

} //~namespace maziak
} //~namespace ribi

#endif // MAZIAKDIFFICULTY_H

 

 

 

 

 

./GameMaziak/maziakdifficulty.cpp

 

#include "maziakdifficulty.h"

 

 

 

 

 

./GameMaziak/maziakdistancesmaze.h

 

#ifndef MAZIAKDISTANCESMAZE_H
#define MAZIAKDISTANCESMAZE_H

#include <vector>

#include "maziakfwd.h"
#include "maziakmazesquare.h"

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include <boost/shared_ptr.hpp>
#pragma GCC diagnostic pop

namespace ribi {
namespace maziak {

///DistancesMaze displays the distances from a goal
/*

456789
3
21012 8
   1 3 7
4323456

*/
struct DistancesMaze
{
  DistancesMaze(
    const boost::shared_ptr<const IntMaze> maze,
    const int goal_x, const int goal_y);

  bool CanGet(const int x, const int y) const noexcept;
  int Get(const int x, const int y) const noexcept;
  int GetSize() const noexcept { return static_cast<int>(m_distances.size()); }

  private:
  const std::vector<std::vector<int>> m_distances;

  static const std::vector<std::vector<int>> CalculateDistances(
    const boost::shared_ptr<const IntMaze> maze,
    const int x, const int y) noexcept;

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif
};

} //~namespace maziak
} //~namespace ribi

#endif // MAZIAKDISTANCESMAZE_H

 

 

 

 

 

./GameMaziak/maziakdistancesmaze.cpp

 

#include "maziakdistancesmaze.h"

#include <cassert>

#include "maziakintmaze.h"
#include "testtimer.h"
#include "trace.h"

ribi::maziak::DistancesMaze::DistancesMaze(
  const boost::shared_ptr<const IntMaze> maze,
  const int x,
  const int y
  )
  : m_distances(CalculateDistances(maze,x,y))
{
  #ifndef NDEBUG
  Test();
  #endif
}

const std::vector<std::vector<int>> ribi::maziak::DistancesMaze::CalculateDistances(
  const boost::shared_ptr<const IntMaze> maze,
  const int x, const int y) noexcept
{
  //Assume maze is square
  assert(maze->IsSquare());
  assert(maze->Get(x,y) == 0); //Assume starting point is no wall

  const int size = maze->GetSize();
  const int area = size * size;
  const int maxDistance = area;
  std::vector<std::vector<int> > distances(size, std::vector<int>(size,maxDistance));
  {
    //Calculate the distances
    int distance = 0;
    distances[y][x] = 0; //Set final point
    std::vector< std::pair<int,int> > found;
    found.push_back(std::make_pair(x,y));

    while(found.empty() == false)
    {
      ++distance;
      std::vector< std::pair<int,int> > newFound;

      const std::vector< std::pair<int,int> >::iterator j = found.end();
      for (std::vector< std::pair<int,int> >::iterator i = found.begin(); i!=j; ++i)
      {
        const int x = (*i).first;
        const int y = (*i).second;

        if (maze->Get(x,y-1) == 0                //No wall
          && distances[y-1][x] == maxDistance) //Not already in solution
        {
          distances[y-1][x] = distance;
          newFound.push_back(std::make_pair(x,y-1));
        }
        if (maze->Get(x,y+1) == 0                //No wall
          && distances[y+1][x] == maxDistance) //Not already in solution
        {
          distances[y+1][x] = distance;
          newFound.push_back(std::make_pair(x,y+1));
        }

        if (maze->Get(x+1,y) == 0                //No wall
          && distances[y][x+1] == maxDistance) //Not already in solution
        {
          distances[y][x+1] = distance;
          newFound.push_back(std::make_pair(x+1,y));
        }

        if (maze->Get(x-1,y) == 0                //No wall
          && distances[y][x-1] == maxDistance) //Not already in solution
        {
          distances[y][x-1] = distance;
          newFound.push_back(std::make_pair(x-1,y));
        }

      }
      found = newFound;
    }
  }
  return distances;
}

bool ribi::maziak::DistancesMaze::CanGet(const int x, const int y) const noexcept
{
  return x >= 0 && x < GetSize()
      && y >= 0 && y < GetSize();
}

int ribi::maziak::DistancesMaze::Get(const int x, const int y) const noexcept
{
  assert(CanGet(x,y));
  return m_distances[y][x];
}

#ifndef NDEBUG
void ribi::maziak::DistancesMaze::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
}
#endif

 

 

 

 

 

./GameMaziak/maziakfwd.h

 

#ifndef MAZIAKFWD_H
#define MAZIAKFWD_H

namespace ribi {
namespace maziak {

struct DistancesMaze;
struct IntMaze;
struct MainDialog;
struct Maze;
struct Sprites;
struct SolutionMaze;

} //~namespace maziak
} //~namespace ribi

#endif // MAZIAKFWD_H

 

 

 

 

 

./GameMaziak/maziakhelper.h

 

#ifndef MAZIAKHELPER_H
#define MAZIAKHELPER_H

#include <cassert>
#include <vector>

#include "maziakmazesquare.h"

namespace ribi {
namespace maziak {

const std::vector<std::pair<int,int> > GetShuffledDeadEnds(
    const std::vector<std::vector<int> >& intMaze);

const std::vector<std::pair<int,int> > GetShuffledNonDeadEnds(
    const std::vector<std::vector<int> >& intMaze);

bool CanMoveTo(
    const std::vector<std::vector<MazeSquare> >& maze,
    const int x, const int y,
    const bool hasSword,
    const bool showSolution);

//From http://www.richelbilderbeek.nl/CppGetDeadEnds.htm
std::vector<std::pair<int,int> > GetDeadEnds(const std::vector<std::vector<int> >& maze);


//From http://www.richelbilderbeek.nl/CppGetMazeDistances.htm
std::vector<std::vector<int> > GetMazeDistances(
    const std::vector<std::vector<int> >& maze,
    const int x,
    const int y);

//const std::vector<std::pair<int,int> > GetShuffledDeadEnds(
//    const std::vector<std::vector<int> >& intMaze);


} //~namespace maziak
} //~namespace ribi

#endif // MAZIAKHELPER_H

 

 

 

 

 

./GameMaziak/maziakhelper.cpp

 

#include "maziakhelper.h"

#include <algorithm>
#include <cassert>
#include <cstdlib>

#include "maziakmazesquare.h"

#include <vector>

 

 

 

 

 

./GameMaziak/maziakintmaze.h

 

#ifndef MAZIAKINTMAZE_H
#define MAZIAKINTMAZE_H

#include <vector>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include <boost/shared_ptr.hpp>

#include "maziakfwd.h"
#pragma GCC diagnostic pop

namespace ribi {
namespace maziak {

///A maze using integers
/// 0 : path
/// 1 : wall
struct IntMaze
{
  IntMaze(const int sz) : IntMaze(CreateMaze(sz)) {}
  IntMaze(const std::vector<std::vector<int> >& maze);

  bool CanGet(const int x, const int y) const noexcept;

  int Get(const int x, const int y) const noexcept;

  const std::vector<std::vector<int>> GetMaze() const noexcept { return m_maze; }

  int GetSize() const noexcept { return static_cast<int>(m_maze.size()); }

  ///Already shuffled, m_dead_ends[0] is the suggested initial coordinat for the player
  const std::vector<std::pair<int,int> > GetDeadEnds() const noexcept { return m_dead_ends; }

  ///Find the distances to (x,y) in walking squared
  const boost::shared_ptr<DistancesMaze> GetDistancesMaze(
    const int x,
    const int y
    ) const noexcept;

  ///Adapted from http://www.richelbilderbeek.nl/CppIsSquare.htm
  bool IsSquare() const noexcept;

  private:

  const std::vector<std::pair<int,int> > m_dead_ends;
  const std::vector<std::vector<int>> m_maze;

  ///From http://www.richelbilderbeek.nl/CppGetDeadEnds.htm
  static const std::vector<std::pair<int,int> > CreateDeadEnds(
    const std::vector<std::vector<int> >& maze) noexcept;

  //Creates a maze
  // 0 : path
  // 1 : wall
  ///From http://www.richelbilderbeek.nl/CppCreateMaze.htm
  static const std::vector<std::vector<int> > CreateMaze(const int sz) noexcept;

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif
};

} //~namespace maziak
} //~namespace ribi

#endif // MAZIAKINTMAZE_H

 

 

 

 

 

./GameMaziak/maziakintmaze.cpp

 

#include "maziakintmaze.h"

#include <algorithm>
#include <cassert>
#include <cstdlib>

#include "maziakdistancesmaze.h"
#include "maziakhelper.h"
#include "testtimer.h"
#include "trace.h"

ribi::maziak::IntMaze::IntMaze(const std::vector<std::vector<int>>& maze)
  : m_dead_ends{CreateDeadEnds(maze)},
    m_maze{maze}
{
  #ifndef NDEBUG
  Test();
  #endif
}

bool ribi::maziak::IntMaze::CanGet(const int x, const int y) const noexcept
{
  return x >= 0 && x < GetSize()
      && y >= 0 && y < GetSize();
}

const std::vector<std::pair<int,int> > ribi::maziak::IntMaze::CreateDeadEnds(
  const std::vector<std::vector<int> >& maze) noexcept
{
  const int size = maze.size();

  std::vector<std::pair<int,int> > dead_ends;

  for (int y=1; y!=size-1; ++y)
  {
    for (int x=1; x!=size-1; ++x)
    {
      if (maze[y][x] != 0) continue; //Continue if here is a wall
      const int nWalls
        = (maze[y+1][x  ] == 1 ? 1 : 0)
        + (maze[y-1][x  ] == 1 ? 1 : 0)
        + (maze[y  ][x+1] == 1 ? 1 : 0)
        + (maze[y  ][x-1] == 1 ? 1 : 0);
      if (nWalls == 3) dead_ends.push_back(std::make_pair(x,y));

    }
  }

  //Shuffle them
  std::random_shuffle(dead_ends.begin(), dead_ends.end());
  return dead_ends;
}

const std::vector<std::vector<int> > ribi::maziak::IntMaze::CreateMaze(const int sz) noexcept
{
  //Assume correct size dimensions
  assert( sz > 4 && sz % 4 == 3
    && "Size must be 3 + (n * 4) for n > 0");

  //Start with a wall-only maze
  std::vector<std::vector<int> > maze(sz, std::vector<int>(sz,1));

  //Prepare maze, remove paths
  // XXXXXXX    1111111
  // X X X X    1212121
  // XXXXXXX    1111111
  // X XOX X -> 1210121
  // XXXXXXX    1111111
  // X X X X    1212121
  // XXXXXXX    1111111

  //Draw open spaces
  for (int y=1; y<sz; y+=2)
  {
    for (int x=1; x<sz; x+=2)
    {
      maze[y][x] = 2; //2: unexplored
    }
  }

  const int mid = sz/2;

  maze[mid][mid] = 0;

  std::vector<std::pair<int,int> > v;
  v.push_back(std::make_pair(mid,mid));
  while (!v.empty())
  {
    //Set a random explorer square at the back
    std::swap(v.back(),v[ std::rand() % static_cast<int>(v.size())]);
    //Check possible adjacent squares
    const int x = v.back().first;
    const int y = v.back().second;
    std::vector<std::pair<int,int> > next;
    if (x > 0 + 2 && maze[y][x-2] == 2) next.push_back(std::make_pair(x-2,y));
    if (y > 0 + 2 && maze[y-2][x] == 2) next.push_back(std::make_pair(x,y-2));
    if (x < sz - 2 && maze[y][x+2] == 2) next.push_back(std::make_pair(x+2,y));
    if (y < sz - 2 && maze[y+2][x] == 2) next.push_back(std::make_pair(x,y+2));
    //Dead end?
    if (next.empty())
    {
      v.pop_back();
      continue;
    }
    //Select a random next adjacent square
    const int nextIndex = (std::rand() >> 4) % static_cast<int>(next.size());
    const int nextX = next[nextIndex].first;
    const int nextY = next[nextIndex].second;
    //Clear next square
    maze[nextY][nextX] = 0;
    //Clear path towards next square
    maze[(y + nextY)/2][(x + nextX)/2] = 0;
    //Add next square to stack
    v.push_back(std::make_pair(nextX,nextY));
  }
  return maze;
}

int ribi::maziak::IntMaze::Get(const int x, const int y) const noexcept
{
  assert(CanGet(x,y));
  return m_maze[y][x];
}

const boost::shared_ptr<ribi::maziak::DistancesMaze> ribi::maziak::IntMaze::GetDistancesMaze(
  const int x,
  const int y
  ) const noexcept
{
  const boost::shared_ptr<const IntMaze> int_maze {
    new IntMaze(m_maze)
  };
  assert(int_maze);

  const boost::shared_ptr<DistancesMaze> maze {
    new DistancesMaze(int_maze,x,y)
  };

  assert(maze);
  return maze;
}



bool ribi::maziak::IntMaze::IsSquare() const noexcept
{
  assert(!m_maze.empty());
  for(std::vector<int> row: m_maze)
  {
    if (row.size()!=m_maze.size()) return false;
  }
  return true;
}

#ifndef NDEBUG
void ribi::maziak::IntMaze::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
}
#endif

 

 

 

 

 

./GameMaziak/maziakkey.h

 

#ifndef MAZIAKKEY_H
#define MAZIAKKEY_H

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic pop

namespace ribi {
namespace maziak {

enum class Key
{
  up, right, down, left
};

} //namespace maziak
} //namespace ribi


#endif // MAZIAKKEY_H

 

 

 

 

 

./GameMaziak/maziakkey.cpp

 

#include "maziakkey.h"

 

 

 

 

 

./GameMaziak/maziakmaindialog.h

 

#ifndef MAZIAKMAINDIALOG_H
#define MAZIAKMAINDIALOG_H

#include <set>
#include <vector>

#include "maziakfwd.h"
#include "maziakkey.h"

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#include <boost/shared_ptr.hpp>
#include <boost/signals2.hpp>
#include "maziakplayerdirection.h"
#include "maziakplayermove.h"
#include "maziaksprite.h"
//#include "widget.h"
#pragma GCC diagnostic pop

namespace ribi {

struct TextCanvas;

namespace maziak {

struct MainDialog
{
  enum class State { playing, has_won, game_over };

  MainDialog(const int maze_size);

  void AnimateEnemiesAndPrisoners(const int view_width, const int view_height) noexcept;

  void AnimateFighting() noexcept;

  bool GetDoShowSolution() const noexcept { return m_do_show_solution; }

  ///Play the game
  void Execute() noexcept;

  const boost::shared_ptr<const Maze> GetMaze() const noexcept { return m_maze; }

  PlayerDirection GetPlayerDirection() const noexcept { return m_direction; }
  int GetPlayerFightingFrame() const noexcept { return m_fighting_frame; }
  bool GetPlayerHasSword() const noexcept { return m_has_sword; }
  PlayerMove GetPlayerMove() const noexcept { return m_move_now; }

  const boost::shared_ptr<const SolutionMaze> GetSolution() const noexcept { return m_solution; }

  Sprite GetSpriteFloor(const int x,const int y) const noexcept { return GetSpriteFloor(m_maze,x,y,m_do_show_solution,m_solution); }
  Sprite GetSpriteAboveFloor(const int x,const int y) const noexcept { return GetSpriteAboveFloor(x,y,m_maze); }
  Sprite GetSpritePlayer() const noexcept { return GetSpritePlayer(m_direction,m_move_now,m_has_sword,m_fighting_frame); }

  State GetState() const noexcept { return m_state; }

  int GetX() const noexcept { return m_x; }
  int GetY() const noexcept { return m_y; }

  ///Add a key
  void OnKeyPress(const Key key);

  ///Press all active keys
  void OnTimerPressKeys();

  ///Remove a key
  void OnKeyRelease(const Key key);

  void RespondToCurrentSquare() noexcept;

  void SetShowSolution(const bool do_show_solution) noexcept { m_do_show_solution = do_show_solution; }

  const boost::shared_ptr<TextCanvas> ToTextCanvas(
    const int view_height,
    const int view_width
  ) const noexcept;

  boost::signals2::signal<void()> m_signal_game_over;
  boost::signals2::signal<void()> m_signal_game_won;
  boost::signals2::signal<void()> m_signal_start_showing_solution;
  boost::signals2::signal<void()> m_signal_stop_showing_solution;
  private:


  PlayerDirection m_direction;
  boost::shared_ptr<const DistancesMaze> m_distances;
  bool m_do_show_solution;
  int m_fighting_frame;
  bool m_has_sword;
  std::set<Key> m_keys;
  const boost::shared_ptr<Maze> m_maze;
  PlayerMove m_move_now;
  boost::shared_ptr<const SolutionMaze> m_solution;
  State m_state;
  int m_x;
  int m_y;

  const boost::shared_ptr<const SolutionMaze> CreateNewSolution() noexcept;

  static Sprite GetSpriteFloor(
    const boost::shared_ptr<const Maze> maze,
    const int x,
    const int y,
    const bool show_solution,
    const boost::shared_ptr<const SolutionMaze> solution
  ) noexcept;
  static Sprite GetSpriteAboveFloor(
    const int x,
    const int y,
    const boost::shared_ptr<const Maze> m_maze
  ) noexcept;
  static Sprite GetSpritePlayer(
    const PlayerDirection direction,
    const PlayerMove moveNow,
    const bool m_has_sword,
    const int m_fighting_frame
  ) noexcept;

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif
};

} //namespace maziak
} //namespace ribi


#endif // MAZIAKMAINDIALOG_H

 

 

 

 

 

./GameMaziak/maziakmaindialog.cpp

 

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#include "maziakmaindialog.h"

#include <cassert>
#include <iostream>

#include "maziakkey.h"
#include "maziakmaze.h"
#include "maziakintmaze.h"
#include "maziakreceiver.h"
#include "maziaksolutionmaze.h"
#include "maziaksprites.h"
#include "testtimer.h"
#include "textcanvas.h"
#include "trace.h"
#pragma GCC diagnostic pop

ribi::maziak::MainDialog::MainDialog(const int maze_size)
  : m_signal_game_over{},
    m_signal_game_won{},
    m_signal_start_showing_solution{},
    m_signal_stop_showing_solution{},
    m_direction(PlayerDirection::pdDown),
    m_distances{},
    m_do_show_solution(false),
    m_fighting_frame(0),
    m_has_sword(true),
    m_keys{},
    m_maze{new Maze(maze_size)},
    m_move_now(PlayerMove::none),
    m_solution{},
    m_state{State::playing},
    m_x(-1),
    m_y(-1)
{
  #ifndef NDEBUG
  Test();
  #endif

  {
    const std::pair<int,int> exit = m_maze->FindExit();
    m_distances = m_maze->GetIntMaze()->GetDistancesMaze(exit.first,exit.second);
  }
  {
    const std::pair<int,int> start = m_maze->FindStart();
    m_x = start.first;
    m_y = start.second;
  }
  assert(maze_size && "Maze size must be 7 + (4 * n) for n e [0,->>");
  assert(m_maze->IsSquare());

  m_solution = CreateNewSolution();

}

void ribi::maziak::MainDialog::AnimateEnemiesAndPrisoners(const int view_width, const int view_height) noexcept
{
  m_maze->AnimateEnemiesAndPrisoners(
    m_x,
    m_y,
    view_width,
    view_height
  );
}

void ribi::maziak::MainDialog::AnimateFighting() noexcept
{
  if (m_fighting_frame > 0)
  {
    ++m_fighting_frame;
    if (m_fighting_frame == 13)
    {
      if (!m_has_sword)
      {
        m_state = State::game_over;
        m_signal_game_over();
        return;
      }
      m_fighting_frame = 0;
      m_has_sword = false;
    }
  }
}

const boost::shared_ptr<const ribi::maziak::SolutionMaze> ribi::maziak::MainDialog::CreateNewSolution() noexcept
{
  const boost::shared_ptr<const SolutionMaze> solution {
    new SolutionMaze(m_distances,m_x,m_y)
  };
  assert(solution);
  return solution;
}


void ribi::maziak::MainDialog::Execute() noexcept
{
  Receiver r;
  m_signal_game_over.connect(boost::bind(&Receiver::OnGameOver,r));
  m_signal_game_won.connect(boost::bind(&Receiver::OnGameWon,r));
  m_signal_start_showing_solution.connect(boost::bind(&Receiver::OnStartShowingSolution,r));
  m_signal_stop_showing_solution.connect(boost::bind(&Receiver::OnStopShowingSolution,r));


  while (1)
  {
    const int width  = 20;
    const int height = 20;
    std::cout << (*ToTextCanvas(width,height)) << std::endl;

    char c;
    std::cin >> c;

    if (!std::cin)
    {
      std::cout
        << "Please enter one of the following characters:" << '\n'
        << "a: move right" << '\n'
        << "s: move down" << '\n'
        << "d: move right" << '\n'
        << "w: move up" << '\n'
        << "q: quit" << '\n'
        << "other: wait" << '\n'
        << std::endl;
      continue;
    }

    switch (c)
    {
      case 'w': this->OnKeyPress(Key::up); break;
      case 'd': this->OnKeyPress(Key::right); break;
      case 's': this->OnKeyPress(Key::down); break;
      case 'a': this->OnKeyPress(Key::left); break;
      case 'q': return;
    }

    OnTimerPressKeys();

    switch (c)
    {
      case 'w': this->OnKeyRelease(Key::up); break;
      case 'd': this->OnKeyRelease(Key::right); break;
      case 's': this->OnKeyRelease(Key::down); break;
      case 'a': this->OnKeyRelease(Key::left); break;
    }

    RespondToCurrentSquare();
    AnimateEnemiesAndPrisoners(width,height);
    if(m_fighting_frame > 0)
    {
      AnimateFighting();
    }
  }
}

ribi::maziak::Sprite ribi::maziak::MainDialog::GetSpriteFloor(
  const boost::shared_ptr<const Maze> maze,
  const int x,
  const int y,
  const bool do_show_solution,
  const boost::shared_ptr<const SolutionMaze> solution
) noexcept
{
  assert(do_show_solution == false || solution->GetSize() == maze->GetSize());
  if (!maze->CanGet(x,y)) { return Sprite::wall; }
  else if (do_show_solution
    && solution->Get(x,y) == 1
    && ( maze->Get(x,y) == MazeSquare::msEmpty
      || maze->Get(x,y) == MazeSquare::msEnemy1
      || maze->Get(x,y) == MazeSquare::msEnemy2)
    )
  {
    return Sprite::path;
  }
  return Sprite::empty;
}

ribi::maziak::Sprite ribi::maziak::MainDialog::GetSpriteAboveFloor(
  const int x,
  const int y,
  const boost::shared_ptr<const Maze> maze
) noexcept
{
  if (!maze->CanGet(x,y)) { return Sprite::wall; }
  //What else here?
  switch(maze->Get(x,y))
  {
    case MazeSquare::msStart     :
    case MazeSquare::msEmpty     : return Sprite::transparent;
    case MazeSquare::msWall      : return Sprite::wall;
    case MazeSquare::msEnemy1    : return Sprite::enemy1;
    case MazeSquare::msEnemy2    : return Sprite::enemy2;
    case MazeSquare::msPrisoner1 : return Sprite::prisoner1;
    case MazeSquare::msPrisoner2 : return Sprite::prisoner2;
    case MazeSquare::msSword     : return Sprite::sword;
    case MazeSquare::msExit      : return Sprite::exit;
    default:
      assert(!"Should not get here");
      throw std::logic_error("Unexpected MazeSquare at mMaze");
  }
}

ribi::maziak::Sprite ribi::maziak::MainDialog::GetSpritePlayer(
  const PlayerDirection direction,
  const PlayerMove move,
  const bool has_sword,
  const int fighting_frame
) noexcept
{
  switch (fighting_frame)
  {
    case  0: break;
    case  1: return has_sword ? Sprite::fight_sword1 : Sprite::fight_no_sword1;
    case  2: return Sprite::fight2;
    case  3: return Sprite::fight3;
    case  4: return Sprite::fight4;
    case  5: return has_sword ? Sprite::fight_sword1 : Sprite::fight_no_sword1;
    case  6: return Sprite::fight2;
    case  7: return Sprite::fight3;
    case  8: return Sprite::fight4;
    case  9: return has_sword ? Sprite::fight_won1 : Sprite::fight_lost1;
    case 10: return has_sword ? Sprite::fight_won2 : Sprite::fight_lost2;
    case 11: return has_sword ? Sprite::fight_won1 : Sprite::fight_lost1;
    case 12: return has_sword ? Sprite::fight_won2 : Sprite::fight_lost2;
  }

  switch (direction)
  {
    case PlayerDirection::pdUp:
    {
      switch (move)
      {
      case PlayerMove::none: return has_sword ? Sprite::player_look_up_sword : Sprite::player_look_up;
      case PlayerMove::up1:  return has_sword ? Sprite::player_walk_up_sword1 : Sprite::player_walk_up1;
      case PlayerMove::up2:  return has_sword ? Sprite::player_walk_up_sword2 : Sprite::player_walk_up2;
      default:
        assert("!Should not get here");
        throw std::logic_error("Unsupported PlayerMove mMoveNow for mDirection == up");
      }
    }
    //break; Unreachable
    case PlayerDirection::pdRight:
    {
      switch (move)
      {
        case PlayerMove::none:   return has_sword ? Sprite::player_look_right_sword : Sprite::player_look_right;
        case PlayerMove::right1: return has_sword ? Sprite::player_walk_right_sword1 : Sprite::player_walk_right1;
        case PlayerMove::right2: return has_sword ? Sprite::player_walk_right_sword2 : Sprite::player_walk_right2;
        default:
          assert("!Should not get here");
          throw std::logic_error("Unsupported PlayerMove mMoveNow for mDirection == right");
      }
    }
    //break; Unreachable
    case PlayerDirection::pdDown:
    {
      switch (move)
      {
      case PlayerMove::none:  return has_sword ? Sprite::player_look_down_sword : Sprite::player_look_down;
      case PlayerMove::down1: return has_sword ? Sprite::player_walk_down_sword1 : Sprite::player_walk_down1;
      case PlayerMove::down2: return has_sword ? Sprite::player_walk_down_sword2 : Sprite::player_walk_down2;
      default:
        assert("!Should not get here");
        throw std::logic_error("Unsupported PlayerMove mMoveNow for mDirection == down");
      }
    }
    //break; Unreachable
    case PlayerDirection::pdLeft:
    {
      switch (move)
      {
        case PlayerMove::none:  return (has_sword ? Sprite::player_look_left_sword : Sprite::player_look_left);
        case PlayerMove::left1: return (has_sword ? Sprite::player_walk_left_sword1 : Sprite::player_walk_left1);
        case PlayerMove::left2: return (has_sword ? Sprite::player_walk_left_sword2 : Sprite::player_walk_left2);
        default:
          assert("!Should not get here");
          throw std::logic_error("Unsupported PlayerMove mMoveNow for mDirection == left");
      }
    }
      //break; Unreachable
    default:
      assert("!Should not get here");
    throw std::logic_error("Unsupported PlayerDirection");
  }
  //Unreachable
}

void ribi::maziak::MainDialog::OnKeyPress(const maziak::Key key)
{
  //if (m_fighting_frame > 0) repaint();
  m_keys.insert(key);

  switch (key)
  {
    case Key::left : m_keys.erase(Key::right); break;
    case Key::right: m_keys.erase(Key::left ); break;
    case Key::up   : m_keys.erase(Key::down ); break;
    case Key::down : m_keys.erase(Key::up   ); break;
  }
}

void ribi::maziak::MainDialog::OnKeyRelease(const maziak::Key key)
{
  m_keys.erase(key);
}

void ribi::maziak::MainDialog::OnTimerPressKeys()
{
  if (m_fighting_frame > 0) return;
  if (m_keys.empty()) { m_move_now = PlayerMove::none; return; }

  for(const Key key: m_keys)
  {
    //Check the keys pressed
    switch (key)
    {
      case Key::left:
        m_direction = PlayerDirection::pdLeft;
        if (!m_maze->CanMoveTo(m_x-1,m_y,m_has_sword,m_do_show_solution))
        {
          m_move_now = PlayerMove::none;
          continue;
        }
        m_move_now = (m_move_now == PlayerMove::left1 ? PlayerMove::left2 : PlayerMove::left1);
        --m_x;
        break;
      case Key::right:
        m_direction = PlayerDirection::pdRight;
        if (!m_maze->CanMoveTo(m_x+1,m_y,m_has_sword,m_do_show_solution))
        {
          m_move_now = PlayerMove::none;
          continue;
        }
        m_move_now = (m_move_now == PlayerMove::right1 ? PlayerMove::right2 : PlayerMove::right1);
        ++m_x;
        break;
      case Key::up:
        m_direction = PlayerDirection::pdUp;
        if (!m_maze->CanMoveTo(m_x,m_y-1,m_has_sword,m_do_show_solution))
        {
          m_move_now = PlayerMove::none;
          continue;
        }
        m_move_now = (m_move_now == PlayerMove::up1 ? PlayerMove::up2 : PlayerMove::up1);
        --m_y;
        break;
      case Key::down:
        m_direction = PlayerDirection::pdDown;
        if (!m_maze->CanMoveTo(m_x,m_y+1,m_has_sword,m_do_show_solution))
        {
          m_move_now = PlayerMove::none;
          continue;
        }
        m_move_now = (m_move_now == PlayerMove::down1 ? PlayerMove::down2 : PlayerMove::down1);
        ++m_y;
        break;
      default:
        m_move_now = PlayerMove::none;
        continue;
    }
  }
}

void ribi::maziak::MainDialog::RespondToCurrentSquare() noexcept
{
  assert(m_maze->CanGet(m_x,m_y));
  switch (m_maze->Get(m_x,m_y))
  {
    case MazeSquare::msStart:
    case MazeSquare::msEmpty:
      break;
    case MazeSquare::msWall:
      assert(!"Should not get here");
      throw std::logic_error("Player cannot be in wall");
    case MazeSquare::msEnemy1: case MazeSquare::msEnemy2:
      m_fighting_frame = 1;
      m_maze->Set(m_x,m_y,MazeSquare::msEmpty);
      break;
    case MazeSquare::msPrisoner1: case MazeSquare::msPrisoner2:
      m_maze->Set(m_x,m_y,MazeSquare::msEmpty);
      m_solution = CreateNewSolution();
      //GetDistancesPath(m_distances,m_x,m_y);
      assert(m_solution->IsSquare());
      m_do_show_solution = true;
      //m_timer_show_solution->start();
      m_signal_start_showing_solution();
      break;
    case MazeSquare::msSword:
      m_maze->Set(m_x,m_y,MazeSquare::msEmpty);
      m_has_sword = true;
      break;
    case MazeSquare::msExit:
    {
      m_state = State::has_won;
      m_signal_game_won();
      break;
    }
    default:
      assert(!"Should not get here");
      break;
  }
}

#ifndef NDEBUG
void ribi::maziak::MainDialog::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
}
#endif

const boost::shared_ptr<ribi::TextCanvas> ribi::maziak::MainDialog::ToTextCanvas(
  const int view_height,
  const int view_width
) const noexcept
{
  const boost::shared_ptr<TextCanvas> canvas {
    new TextCanvas(view_height,view_width)
  };
  if (GetState() == State::has_won)
  {
    canvas->PutText(1,1,"You");
    canvas->PutText(1,2,"won");
    canvas->PutText(1,3,"the");
    canvas->PutText(1,4,"game");
    return canvas;
  }
  else if (GetState() == State::game_over)
  {
    canvas->PutText(1,1,"GAME");
    canvas->PutText(1,2,"OVER");
    return canvas;
  }

  //Draw maze
  {
    for (int y=0; y!=view_height; ++y)
    {
      for (int x=0; x!=view_width; ++x)
      {
        //xVector and yVector are the indices in the non-visual maze 2D std::vector
        const int xVector = GetX() - (view_width  / 2) + x;
        const int yVector = GetY() - (view_height / 2) + y;
        //Draw the floor tile
        const char pixmap_floor {
          Sprites::ToChar(
            GetSpriteFloor(
              GetMaze(),
              xVector,
              yVector,
              GetDoShowSolution(),
              GetSolution()
            )
          )
        };
        canvas->PutChar(x,y,pixmap_floor);
        //Draw what's moving or standing on the floor
        const Sprite sprite_above_floor {
          GetSpriteAboveFloor(xVector,yVector,GetMaze())
        };
        if (sprite_above_floor != Sprite::transparent)
        {
          const char pixmap_above_floor {
            Sprites::ToChar(sprite_above_floor)
          };
          canvas->PutChar(x,y,pixmap_above_floor);
        }
      }
    }
  }

  //Draw player
  {
    const char player {
      Sprites::ToChar(
        GetSpritePlayer(
          GetPlayerDirection(),
          GetPlayerMove(),
          GetPlayerHasSword(),
          GetPlayerFightingFrame()
        )
      )
    };
    assert(player);
    canvas->PutChar(view_width/2,view_height / 2,player);
  }
  return canvas;
}

 

 

 

 

 

./GameMaziak/maziakmaze.h

 

#ifndef MAZIAKMAZE_H
#define MAZIAKMAZE_H

#include <vector>

#include "maziakfwd.h"
#include "maziakmazesquare.h"

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include <boost/shared_ptr.hpp>
#pragma GCC diagnostic pop

namespace ribi {
namespace maziak {

struct Maze
{
  Maze(const int size) : Maze(CreateIntMaze(size)) {}
  Maze(const boost::shared_ptr<const IntMaze> int_maze);

  ///Animate the enemies and prisoners in sight
  ///(all others are just standing still)
  void AnimateEnemiesAndPrisoners(
    const int x,
    const int y,
    const int view_width,
    const int view_height
    ) noexcept;

  bool CanGet(const int x, const int y) const noexcept;
  bool CanSet(const int x, const int y, const MazeSquare s) const noexcept;

  ///Can a player move to coordinat (x,y) ?
  bool CanMoveTo(
    const int x, const int y,
    const bool hasSword,
    const bool showSolution) const noexcept;

  const std::pair<int,int> FindExit() const noexcept;
  const std::pair<int,int> FindStart() const noexcept;

  MazeSquare Get(const int x, const int y) const noexcept;

  const boost::shared_ptr<const IntMaze> GetIntMaze() const noexcept { return m_int_maze; }

  int GetSize() const noexcept { return static_cast<int>(m_maze.size()); }

  ///Adapted from http://www.richelbilderbeek.nl/CppIsSquare.htm
  bool IsSquare() const noexcept;

  void Set(const int x, const int y, const MazeSquare s) noexcept;

  private:
  const boost::shared_ptr<const IntMaze> m_int_maze;
  std::vector<std::vector<MazeSquare> > m_maze;

  static const boost::shared_ptr<const IntMaze> CreateIntMaze(const int size) noexcept;

  static const std::vector<std::vector<MazeSquare> > CreateMaze(
    const boost::shared_ptr<const IntMaze> int_maze) noexcept;

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif

};

} //~namespace maziak
} //~namespace ribi


#endif // MAZIAKMAZE_H

 

 

 

 

 

./GameMaziak/maziakmaze.cpp

 

#include "maziakmaze.h"

#include <cassert>

#include "testtimer.h"
#include "maziakintmaze.h"
#include "trace.h"

template <class Source, class Target>
    const std::vector<std::vector<Target> > ConvertMatrix(
        const std::vector<std::vector<Source> >& v)
{
  const int maxy = static_cast<int>(v.size());
  assert(maxy>0);
  const int maxx = static_cast<int>(v[0].size());
  std::vector<std::vector<Target> > t(maxy,std::vector<Target>(maxx));
  for (int y=0; y!=maxy; ++y)
  {
    for (int x=0; x!=maxx; ++x)
    {
      t[y][x] = static_cast<Target>(v[y][x]);
    }
  }
  return t;
}

ribi::maziak::Maze::Maze(const boost::shared_ptr<const IntMaze> int_maze)
  : m_int_maze(int_maze),
    m_maze(CreateMaze(int_maze))
{
  #ifndef NDEBUG
  Test();
  #endif
  assert(int_maze->IsSquare());
  assert(IsSquare());
  assert(FindExit().first  >= 0);
  assert(FindStart().first >= 0);
}

void ribi::maziak::Maze::AnimateEnemiesAndPrisoners(
  const int x,
  const int y,
  const int view_width,
  const int view_height
  ) noexcept
{
  //Move them
  const int minx = std::max(0,x - view_width );
  const int miny = std::max(0,y - view_height);
  assert(IsSquare());
  const int maxy = std::min(GetSize(),y + view_height);
  const int maxx = std::min(GetSize(),x + view_width);
  assert(miny >= 0);
  assert(miny <= GetSize());
  assert(maxy >= 0);
  assert(maxy <= GetSize());
  assert(minx >= 0);
  assert(minx <= GetSize());
  assert(maxx >= 0);
  assert(maxx <= GetSize());
  assert(miny <= maxy);
  assert(minx <= maxx);
  for (int row=miny; row!=maxy; ++row)
  {
    assert(row >= 0);
    assert(row < GetSize());
    for (int col=minx; col!=maxx; ++col)
    {
      //msEnemy1 changes to msEnemy2
      //Only msEnemy2 moves, after moving turning to msEnemy1
      assert(col >= 0);
      assert(col < GetSize());
      const MazeSquare s = Get(col,row);

      if (s == MazeSquare::msEnemy1)
      {
        //msEnemy1 changes to msEnemy2
        Set(col,row,MazeSquare::msEnemy2);
        continue;
      }
      else if (s == MazeSquare::msEnemy2)
      {
        //msEnemy 2 tries to walk and becomes msEnemy1
        std::vector<std::pair<int,int> > moves;
        if (row > y && row >        1 && Get(col,row-1) == MazeSquare::msEmpty) moves.push_back(std::make_pair(col,row-1));
        if (col < x && col < maxx - 1 && Get(col+1,row) == MazeSquare::msEmpty) moves.push_back(std::make_pair(col+1,row));
        if (row < y && row < maxy - 1 && Get(col,row+1) == MazeSquare::msEmpty) moves.push_back(std::make_pair(col,row+1));
        if (col > x && col >        1 && Get(col-1,row) == MazeSquare::msEmpty) moves.push_back(std::make_pair(col-1,row));
        const int nMoves = static_cast<int>(moves.size());
        if (nMoves == 1)
        {
          Set(moves[0].first,moves[0].second,MazeSquare::msEnemy1);
          Set(col,row,MazeSquare::msEmpty);
        }
        else if (nMoves > 1)
        {
          assert(nMoves == 2);
          const int moveIndex = (std::rand() >> 4) % nMoves;

          Set(moves[moveIndex].first,moves[moveIndex].second,MazeSquare::msEnemy1);
          Set(col,row,MazeSquare::msEmpty);
        }
      }
      else if (s==MazeSquare::msPrisoner1)
      {
        //Animate prisoners
        Set(col,row,MazeSquare::msPrisoner2);
      }
      else if (s==MazeSquare::msPrisoner2)
      {
        //Animate prisoners
        Set(col,row,MazeSquare::msPrisoner1);
      }
    }
  }
}

bool ribi::maziak::Maze::CanGet(const int x, const int y) const noexcept
{
  return x >= 0 && x < GetSize()
    && y >= 0 && y < GetSize();
}

bool ribi::maziak::Maze::CanMoveTo(
  const int x, const int y,
  const bool hasSword,
  const bool showSolution) const noexcept
{
  //Bump into edge
  if (x < 0) return false;
  if (y < 0) return false;
  const int maxy = static_cast<int>(m_maze.size());
  if (y >= maxy) return false;
  if (x >= static_cast<int>(m_maze[y].size())) return false;
  const MazeSquare s = m_maze[y][x];
  //Bump into wall
  if (s == MazeSquare::msWall) return false;
  //Bump into sword
  if (s == MazeSquare::msSword && hasSword) return false;
  //Bump into prisoner
  if (showSolution
    && (s == MazeSquare::msPrisoner1
     || s == MazeSquare::msPrisoner2) ) return false;
  //Bump into empty/enemy/exit, so player can move there
  return true;
}

bool ribi::maziak::Maze::CanSet(const int x, const int y, const MazeSquare /* s */) const noexcept
{
  return CanGet(x,y);
}

const boost::shared_ptr<const ribi::maziak::IntMaze> ribi::maziak::Maze::CreateIntMaze(const int size) noexcept
{
  assert( size > 4 && size % 4 == 3
    && "Size must be 3 + (n * 4) for n > 0");
  const boost::shared_ptr<const IntMaze> maze {
    new IntMaze(size)
  };
  assert(maze);
  return maze;
}

const std::vector<std::vector<ribi::maziak::MazeSquare> > ribi::maziak::Maze::CreateMaze(
  const boost::shared_ptr<const IntMaze> int_maze) noexcept
{
  assert(int_maze);
  const int sz = int_maze->GetSize();
  std::vector<std::vector<ribi::maziak::MazeSquare> > maze {
    ConvertMatrix<int,MazeSquare>(int_maze->GetMaze())
  };

  std::vector<std::pair<int,int> > dead_ends = int_maze->GetDeadEnds();
  const int nDeadEnds = dead_ends.size();
  assert(nDeadEnds >= 2);
  const int nSwords    = (nDeadEnds - 2) / 3;
  const int nPrisoners = (nDeadEnds - 2) / 10;
  const int nEnemies   = (nDeadEnds - 2) / 4;

  {
    //Set a minimum distance for the player to travel
    while (1)
    {
      const double x1 = static_cast<double>(dead_ends[0].first );
      const double y1 = static_cast<double>(dead_ends[0].second);
      const double x2 = static_cast<double>(dead_ends[1].first );
      const double y2 = static_cast<double>(dead_ends[1].second);
      const double a = x1 - x2;
      const double b = y1 - y2;
      const double minDist = 0.75 * static_cast<double>(sz);
      if (std::sqrt( (a * a) + (b * b) ) > minDist)
      {
        break;
      }
      else
      {

        std::swap(dead_ends[0],dead_ends[std::rand() % nDeadEnds]);
        std::swap(dead_ends[1],dead_ends[std::rand() % nDeadEnds]);
      }
    }
  }
  //Set start
  {
    const int x = dead_ends[0].first;
    const int y = dead_ends[0].second;
    assert(maze[y][x] == MazeSquare::msEmpty);
    maze[y][x] = MazeSquare::msStart;
  }
  //Set exit
  {
    const int x = dead_ends[1].first;
    const int y = dead_ends[1].second;
    assert(maze[y][x] == MazeSquare::msEmpty);
    maze[y][x] = MazeSquare::msExit;
  }


  std::vector<std::pair<int,int> >::const_iterator deadEndIterator = dead_ends.begin() + 2;

  {
    //Place swords in maze, only in dead ends
    for (int i=0; i!=nSwords; ++i)
    {
      assert(deadEndIterator != dead_ends.end());
      const int x = (*deadEndIterator).first;
      const int y = (*deadEndIterator).second;
      assert(maze[y][x] == MazeSquare::msEmpty);
      maze[y][x] = MazeSquare::msSword;
      ++deadEndIterator;
    }
    //Place prisoners in maze, only in dead ends
    for (int i=0; i!=nPrisoners; ++i)
    {
      assert(deadEndIterator != dead_ends.end());
      const int x = (*deadEndIterator).first;
      const int y = (*deadEndIterator).second;
      assert(maze[y][x] == MazeSquare::msEmpty);
      maze[y][x] = MazeSquare::msPrisoner1;
      ++deadEndIterator;
    }

    for (int i=0; i!=nEnemies; ++i)
    {
      assert(deadEndIterator != dead_ends.end());
      const int x = (*deadEndIterator).first;
      const int y = (*deadEndIterator).second;
      assert(maze[y][x] == MazeSquare::msEmpty);
      maze[y][x] = MazeSquare::msEnemy1;
      ++deadEndIterator;
    }
  }
  return maze;
}

const std::pair<int,int> ribi::maziak::Maze::FindExit() const noexcept
{
  for (std::pair<int,int> p: GetIntMaze()->GetDeadEnds())
  {
    if (Get(p.first,p.second) == MazeSquare::msExit) return p;
  }
  assert(!"Should not get here");
  throw std::logic_error("Cannot find exit");
}

const std::pair<int,int> ribi::maziak::Maze::FindStart() const noexcept
{
  for (std::pair<int,int> p: GetIntMaze()->GetDeadEnds())
  {
    if (Get(p.first,p.second) == MazeSquare::msStart) return p;
  }
  assert(!"Should not get here");
  throw std::logic_error("Cannot find start");
}

ribi::maziak::MazeSquare ribi::maziak::Maze::Get(const int x, const int y) const noexcept
{
  assert(CanGet(x,y));
  return m_maze[y][x];
}

bool ribi::maziak::Maze::IsSquare() const noexcept
{
  assert(!m_maze.empty());
  for(std::vector<MazeSquare> row: m_maze)
  {
    if (row.size()!=m_maze.size()) return false;
  }
  return true;
}

void ribi::maziak::Maze::Set(const int x, const int y, const MazeSquare s) noexcept
{
  assert(CanSet(x,y,s));
  m_maze[y][x] = s;
  assert(Get(x,y) == s);
}

#ifndef NDEBUG
void ribi::maziak::Maze::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
}
#endif

 

 

 

 

 

./GameMaziak/maziakmazesquare.h

 

#ifndef MAZIAKMAZESQUARE_H
#define MAZIAKMAZESQUARE_H

namespace ribi {
namespace maziak {

enum class MazeSquare
{
  msEmpty,
  msWall,
  msEnemy1,
  msEnemy2,
  msPrisoner1,
  msPrisoner2,
  msSword,
  msExit,
  msStart //Initial starting position
};

} //~namespace maziak
} //~namespace ribi

#endif // MAZIAKMAZESQUARE_H

 

 

 

 

 

./GameMaziak/maziakmazesquare.cpp

 

#include "maziakmazesquare.h"

 

 

 

 

 

./GameMaziak/maziakmenudialog.h

 

//---------------------------------------------------------------------------
/*
Maziak, a simple maze game
Copyright (C) 2007-2014 Richel Bilderbeek

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/GameMaziak.htm
//---------------------------------------------------------------------------
#ifndef MAZIAKMENUDIALOG_H
#define MAZIAKMENUDIALOG_H

#include "menudialog.h"

namespace ribi {
namespace maziak {

struct MenuDialog final : public ::ribi::MenuDialog
{
  MenuDialog();
  About GetAbout() const noexcept override;
  Help GetHelp() const noexcept override;
  boost::shared_ptr<const Program> GetProgram() const noexcept override;
  std::string GetVersion() const noexcept override;
  std::vector<std::string> GetVersionHistory() const noexcept override;

  private:
  int ExecuteSpecific(const std::vector<std::string>& argv) noexcept override;

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif
};

} //~namespace maziak
} //~namespace ribi

#endif // MAZIAKMENUDIALOG_H

 

 

 

 

 

./GameMaziak/maziakmenudialog.cpp

 

//---------------------------------------------------------------------------
/*
Maziak, a simple maze game
Copyright (C) 2007-2014 Richel Bilderbeek

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/GameMaziak.htm
//---------------------------------------------------------------------------
#include "maziakmenudialog.h"

#include <cassert>
#include <iostream>
#include <sstream>
#include <stdexcept>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#include "maziakmaindialog.h"
#include "testtimer.h"
#include "textcanvas.h"
#include "richelbilderbeekprogram.h"
#include "trace.h"
#pragma GCC diagnostic pop

ribi::maziak::MenuDialog::MenuDialog()
{
  #ifndef NDEBUG
  Test();
  #endif
}

int ribi::maziak::MenuDialog::ExecuteSpecific(const std::vector<std::string>& argv) noexcept
{
  const int argc = static_cast<int>(argv.size());
  if (argc != 1)
  {
    std::cout << GetHelp() << '\n';
    return 1;
  }

  boost::shared_ptr<MainDialog> dialog {
    new MainDialog( 7 + (4 * 2) )
  };
  dialog->Execute();
  return 0;

}

ribi::About ribi::maziak::MenuDialog::GetAbout() const noexcept
{
  About a(
    "Richel Bilderbeek",
    "Maziak",
    "a simple maze game",
    "the 28th of January 2014",
    "2007-2014",
    "http://www.richelbilderbeek.nl/GameMaziak.htm",
    GetVersion(),
    GetVersionHistory()
  );
  a.AddLibrary("TestTimer version: " + TestTimer::GetVersion());
  return a;
}

ribi::Help ribi::maziak::MenuDialog::GetHelp() const noexcept
{
  return Help(
    this->GetAbout().GetFileTitle(),
    this->GetAbout().GetFileDescription(),
    {

    },
    {

    }
  );
}

boost::shared_ptr<const ribi::Program> ribi::maziak::MenuDialog::GetProgram() const noexcept
{
  const boost::shared_ptr<const ribi::Program> p {
    new ProgramMaziak
  };
  assert(p);
  return p;
}

std::string ribi::maziak::MenuDialog::GetVersion() const noexcept
{
  return "3.0";
}

std::vector<std::string> ribi::maziak::MenuDialog::GetVersionHistory() const noexcept
{
  return {
    "2007-10-22: version 1.0: Initial version",
    "2010-02-16: version 1.1: Changed graphics to resemble the original Maziacs more. Changed manu screen. Changed 'Game Over' screen. Changed 'Congratulations' screen.",
    "2010-02-17: version 1.2: Animated prisoners. Animated enemies. Animated player. Improved 'Menu' screen. Improved 'About' screen. Added 'What's New?' screen",
    "2010-02-18: version 1.3: Animated fights. Prevent overlapping sprites. Add 'Instructions' screen in menu. Improved 'Menu' screen",
    "2010-02-25: version 1.4: Improved 'Game Over' screen. Added animation in 'Congratulations' screen. Improved enemies' intelligence. Improved maze creation algorithm. Ensured the player is not placed too close to the exit.",
    "2010-07-31: version 2.0: Reprogrammed in Qt Creator, so Maziak is now cross-platform!",
    "2012-03-06: version 2.1: Conformized architecture and naming for ProjectRichelBilderbeek."
    "2014-01-06: version 3.0: Seperated GUI from game logic, allow console gaming"
  };
}

#ifndef NDEBUG
void ribi::maziak::MenuDialog::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
}
#endif

 

 

 

 

 

./GameMaziak/maziakplayerdirection.h

 

#ifndef MAZIAKPLAYERDIRECTION_H
#define MAZIAKPLAYERDIRECTION_H

namespace ribi {
namespace maziak {

enum class PlayerDirection { pdLeft, pdRight, pdUp, pdDown };

} //~namespace maziak
} //~namespace ribi

#endif // MAZIAKPLAYERDIRECTION_H

 

 

 

 

 

./GameMaziak/maziakplayerdirection.cpp

 

#include "maziakplayerdirection.h"

 

 

 

 

 

./GameMaziak/maziakplayermove.h

 

#ifndef MAZIAKPLAYERMOVE_H
#define MAZIAKPLAYERMOVE_H

namespace ribi {
namespace maziak {

enum class PlayerMove { none, left1, left2, right1, right2, up1, up2, down1, down2 };

} //~namespace maziak
} //~namespace ribi

#endif // MAZIAKPLAYERMOVE_H

 

 

 

 

 

./GameMaziak/maziakplayermove.cpp

 

#include "maziakplayermove.h"

 

 

 

 

 

./GameMaziak/maziakreceiver.h

 

#ifndef MAZIAKRECEIVER_H
#define MAZIAKRECEIVER_H

namespace ribi {
namespace maziak {

///Class used by MainDialog to receive its own signals
struct Receiver
{
  Receiver();

  ///Has the game been lost?
  bool IsGameOver() const noexcept { return m_is_game_over; }

  ///Has the game been won?
  bool IsGameWon() const noexcept { return m_is_game_won; }

  void OnGameOver() noexcept { m_is_game_over = true; }
  void OnGameWon()  noexcept { m_is_game_won = true;  }
  void OnStartShowingSolution() noexcept { m_show_solution = true; }
  void OnStopShowingSolution()  noexcept { m_show_solution = false; }

  ///Should the solution stop being shown
  bool StopShowingSolution() const noexcept { return m_stop_showing_solution; }

  ///Indicate the solution has already stopped being shown
  void StoppedShowingSolution() noexcept { m_stop_showing_solution = false; }

  private:

  bool m_is_game_over;
  bool m_is_game_won;
  bool m_show_solution;
  bool m_stop_showing_solution;

};

} //~namespace maziak
} //~namespace ribi


#endif // MAZIAKRECEIVER_H

 

 

 

 

 

./GameMaziak/maziakreceiver.cpp

 

#include "maziakreceiver.h"

ribi::maziak::Receiver::Receiver()
  : m_is_game_over(false),
    m_is_game_won(false),
    m_show_solution(false),
    m_stop_showing_solution(false)
{

}

 

 

 

 

 

./GameMaziak/maziaksolutionmaze.h

 

#ifndef MAZIAKSOLUTIONMAZE_H
#define MAZIAKSOLUTIONMAZE_H

#include <vector>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include <boost/shared_ptr.hpp>

#include "maziakfwd.h"
#pragma GCC diagnostic pop

namespace ribi {
namespace maziak {

///SolutionMaze displays the solution from a goal (as obtained
///from a DistanceMaze) and a current position
/*

* : solution
. : other corridors

***...
*
***.. .
. . . .
. .....

*/

struct SolutionMaze
{
  SolutionMaze(
    const boost::shared_ptr<const DistancesMaze> maze,
    const int x,
    const int y
  );

  int Get(const int x, const int y) const noexcept;
  int GetSize() const noexcept;
  bool IsSquare() const noexcept;

  private:

  const boost::shared_ptr<const IntMaze> m_maze;

  static const boost::shared_ptr<const IntMaze> CreateSolution(
    const boost::shared_ptr<const DistancesMaze> maze,
    const int x,
    const int y
  ) noexcept;


  #ifndef NDEBUG
  static void Test() noexcept;
  #endif
};

} //~namespace maziak
} //~namespace ribi

#endif // MAZIAKSOLUTIONMAZE_H

 

 

 

 

 

./GameMaziak/maziaksolutionmaze.cpp

 

#include "maziaksolutionmaze.h"

#include <cassert>

#include "maziakdistancesmaze.h"
#include "maziakintmaze.h"
#include "testtimer.h"
#include "trace.h"

ribi::maziak::SolutionMaze::SolutionMaze(
  const boost::shared_ptr<const DistancesMaze> maze,
  const int x,
  const int y
) : m_maze(CreateSolution(maze,x,y))
{
  #ifndef NDEBUG
  Test();
  #endif

}

//From http://www.richelbilderbeek.nl/GetDistancesPath.htm
const boost::shared_ptr<const ribi::maziak::IntMaze> ribi::maziak::SolutionMaze::CreateSolution(
  const boost::shared_ptr<const DistancesMaze> distances,
  const int player_x,
  const int player_y
) noexcept
{
  const int size = distances->GetSize();

  std::vector<std::vector<int> > solution(size, std::vector<int>(size,0));
  {
    int x = player_x;
    int y = player_y;
    int distance = distances->Get(x,y) - 1;
    while (distance >= 0)
    {
      //We must be where we are now
      solution[y][x] = 1;
      if ( x!=0      && distances->Get(x-1,y) == distance ) { --x; --distance; continue; }
      if ( x!=size-1 && distances->Get(x+1,y) == distance ) { ++x; --distance; continue; }
      if ( y!=0      && distances->Get(x,y-1) == distance ) { --y; --distance; continue; }
      if ( y!=size-1 && distances->Get(x,y+1) == distance ) { ++y; --distance; continue; }
    }
  }

  const boost::shared_ptr<const IntMaze> maze {
    new IntMaze(solution)
  };
  assert(maze);
  return maze;
}

int ribi::maziak::SolutionMaze::Get(const int x, const int y) const noexcept
{
  assert(m_maze);
  return m_maze->Get(x,y);
}

int ribi::maziak::SolutionMaze::GetSize() const noexcept
{
  assert(m_maze);
  return m_maze->GetSize();
}

bool ribi::maziak::SolutionMaze::IsSquare() const noexcept
{
  assert(m_maze);
  return m_maze->IsSquare();
}

#ifndef NDEBUG
void ribi::maziak::SolutionMaze::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
}
#endif

 

 

 

 

 

./GameMaziak/maziaksprite.h

 

#ifndef MAZIAKSPRITE_H
#define MAZIAKSPRITE_H

namespace ribi {
namespace maziak {

enum class Sprite
{
  //Floor
  empty,
  wall,
  path,
  transparent,
  //Player sprites
  player_look_down,
  player_look_down_sword,
  player_look_left,
  player_look_left_sword,
  player_look_right,
  player_look_right_sword,
  player_look_up,
  player_look_up_sword,
  player_walk_left1,
  player_walk_left2,
  player_walk_left_sword1,
  player_walk_left_sword2,
  player_walk_right1,
  player_walk_right2,
  player_walk_right_sword1,
  player_walk_right_sword2,
  player_walk_down1,
  player_walk_down2,
  player_walk_down_sword1,
  player_walk_down_sword2,
  player_walk_up1,
  player_walk_up2,
  player_walk_up_sword1,
  player_walk_up_sword2,
  player_won1,
  player_won2,
  //Fighting sprites
  fight_sword1,
  fight_no_sword1,
  fight2,
  fight3,
  fight4,
  fight_won1,
  fight_won2,
  fight_lost1,
  fight_lost2,
  //Non-player sprites
  enemy1,
  enemy2,
  prisoner1,
  prisoner2,
  sword,
  exit,

  n_sprites //Never use, used for debugging
};

} //~namespace maziak
} //~namespace ribi

#endif // MAZIAKSPRITE_H

 

 

 

 

 

./GameMaziak/maziaksprite.cpp

 

#include "maziaksprite.h"

 

 

 

 

 

./GameMaziak/maziaksprites.h

 

#ifndef MAZIAKSPRITES_H
#define MAZIAKSPRITES_H

#include <map>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include <boost/shared_ptr.hpp>

#include "maziaksprite.h"
#pragma GCC diagnostic pop

struct QPixmap;

namespace ribi {
namespace maziak {

struct Sprites
{
  Sprites();
  const boost::shared_ptr<const QPixmap> Get(const Sprite sprite) const noexcept;

  ///ASCII art
  static char ToChar(const Sprite) noexcept;

  private:
  const std::map<Sprite,boost::shared_ptr<const QPixmap>> m_sprites;

  static std::string CamelCasify(const std::string& s) noexcept;
  const std::map<Sprite,boost::shared_ptr<const QPixmap>> CreateSprites();
  static const std::vector<Sprite> GetAllSprites() noexcept;

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif

  static std::string ToStr(const Sprite) noexcept;
};

} //~namespace maziak
} //~namespace ribi

#endif // MAZIAKSPRITES_H

 

 

 

 

 

./GameMaziak/maziaksprites.cpp

 

#include "maziaksprites.h"

#include <cassert>
#include <stdexcept>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include <QPixmap>

#include "testtimer.h"
#include "trace.h"
#pragma GCC diagnostic pop

ribi::maziak::Sprites::Sprites()
  : m_sprites(CreateSprites())
{
  #ifndef NDEBUG
  Test();
  #endif
}

std::string ribi::maziak::Sprites::CamelCasify(const std::string& s) noexcept
{
  std::string t;
  const std::size_t sz = s.size();
  for(std::size_t i = 0;i!=sz;++i)
  {
    const char c = s[i];
    if (s[i] == '_')
    {
      assert(i + 1 < s.size());
      ++i;
      const char d = std::toupper(s[i]);
      t += d;
    }
    else
    {
      t += c;
    }
  }
  return t;
}

const std::map<ribi::maziak::Sprite,boost::shared_ptr<const QPixmap>> ribi::maziak::Sprites::CreateSprites()
{
  std::map<ribi::maziak::Sprite,boost::shared_ptr<const QPixmap>> m;
  const std::vector<Sprite> v { GetAllSprites() };
  for (const Sprite sprite: v)
  {
    std::string spritename { ToStr(sprite) };
    spritename[0] = std::toupper(spritename[0]);
    spritename = CamelCasify(spritename);

    const std::string filename {
      ":/images/" + spritename + ".png"
    };

    const boost::shared_ptr<const QPixmap> pixmap {
      new QPixmap(filename.c_str())
    };
    if (pixmap->width() == 0)
    {
      TRACE("Pixmap not found");
      TRACE(filename);
    }
    assert(pixmap);
    assert(pixmap->width() > 0);
    assert(pixmap->height() > 0);
    m.insert(std::make_pair(sprite,pixmap));
  }
  return m;
}

const boost::shared_ptr<const QPixmap> ribi::maziak::Sprites::Get(const Sprite sprite) const noexcept
{
  assert(m_sprites.find(sprite) != m_sprites.end());
  const boost::shared_ptr<const QPixmap> pixmap {
    m_sprites.find(sprite)->second
  };
  assert(pixmap);
  return pixmap;
}

const std::vector<ribi::maziak::Sprite> ribi::maziak::Sprites::GetAllSprites() noexcept
{
  const std::vector<Sprite> v {
    Sprite::empty,
    Sprite::wall,
    Sprite::path,
    Sprite::transparent,
    Sprite::player_look_down,
    Sprite::player_look_down_sword,
    Sprite::player_look_left,
    Sprite::player_look_left_sword,
    Sprite::player_look_right,
    Sprite::player_look_right_sword,
    Sprite::player_look_up,
    Sprite::player_look_up_sword,
    Sprite::player_walk_left1,
    Sprite::player_walk_left2,
    Sprite::player_walk_left_sword1,
    Sprite::player_walk_left_sword2,
    Sprite::player_walk_right1,
    Sprite::player_walk_right2,
    Sprite::player_walk_right_sword1,
    Sprite::player_walk_right_sword2,
    Sprite::player_walk_down1,
    Sprite::player_walk_down2,
    Sprite::player_walk_down_sword1,
    Sprite::player_walk_down_sword2,
    Sprite::player_walk_up1,
    Sprite::player_walk_up2,
    Sprite::player_walk_up_sword1,
    Sprite::player_walk_up_sword2,
    Sprite::player_won1,
    Sprite::player_won2,
    Sprite::fight_sword1,
    Sprite::fight_no_sword1,
    Sprite::fight2,
    Sprite::fight3,
    Sprite::fight4,
    Sprite::fight_won1,
    Sprite::fight_won2,
    Sprite::fight_lost1,
    Sprite::fight_lost2,
    Sprite::enemy1,
    Sprite::enemy2,
    Sprite::prisoner1,
    Sprite::prisoner2,
    Sprite::sword,
    Sprite::exit
  };
  assert(static_cast<int>(v.size()) == static_cast<int>(Sprite::n_sprites)
    && "All Sprite values (except Sprite::n_sprites) must be in");

  return v;
}

#ifndef NDEBUG
void ribi::maziak::Sprites::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
  assert(CamelCasify("player_look_down_sword") == "playerLookDownSword");
}
#endif

char ribi::maziak::Sprites::ToChar(const ribi::maziak::Sprite sprite) noexcept
{
  switch (sprite)
  {
    case Sprite::empty: return ' ';
    case Sprite::wall: return 'X';
    case Sprite::path: return '.';
    case Sprite::transparent: return ' ';
    case Sprite::player_look_down: return 'v';
    case Sprite::player_look_down_sword: return 'w';
    case Sprite::player_look_left: return '<';
    case Sprite::player_look_left_sword: return 'E';
    case Sprite::player_look_right: return '>';
    case Sprite::player_look_right_sword: return '3';
    case Sprite::player_look_up: return 'A';
    case Sprite::player_look_up_sword: return 'M';
    case Sprite::player_walk_left1: return '\\';
    case Sprite::player_walk_left2: return '/';
    case Sprite::player_walk_left_sword1: return '=';
    case Sprite::player_walk_left_sword2: return 'E';
    case Sprite::player_walk_right1: return '\\';
    case Sprite::player_walk_right2: return '/';
    case Sprite::player_walk_right_sword1: return '=';
    case Sprite::player_walk_right_sword2: return '3';
    case Sprite::player_walk_down1: return '\\';
    case Sprite::player_walk_down2: return '/';
    case Sprite::player_walk_down_sword1: return 'W';
    case Sprite::player_walk_down_sword2: return 'w';
    case Sprite::player_walk_up1: return '/';
    case Sprite::player_walk_up2: return '\\';
    case Sprite::player_walk_up_sword1: return 'm';
    case Sprite::player_walk_up_sword2: return 'M';
    case Sprite::player_won1: return '!';
    case Sprite::player_won2: return '!';
    case Sprite::fight_sword1: return '#';
    case Sprite::fight_no_sword1: return '+';
    case Sprite::fight2: return '*';
    case Sprite::fight3: return '%';
    case Sprite::fight4: return '@';
    case Sprite::fight_won1: return 'W';
    case Sprite::fight_won2: return 'w';
    case Sprite::fight_lost1: return 'Z';
    case Sprite::fight_lost2: return 'z';
    case Sprite::enemy1: return 'Z';
    case Sprite::enemy2: return 'z';
    case Sprite::prisoner1: return ':';
    case Sprite::prisoner2: return ';';
    case Sprite::sword: return '+';
    case Sprite::exit: return '!';
    case Sprite::n_sprites:
      assert(!"Should never use Sprite::n_sprites");
      throw std::logic_error("Never use Sprite::n_sprites");
  }
  assert(!"Should not get here");
  throw std::logic_error("Unknown Sprite");
}

std::string ribi::maziak::Sprites::ToStr(const ribi::maziak::Sprite sprite) noexcept
{
  switch (sprite)
  {
    case Sprite::empty: return "empty";
    case Sprite::wall: return "wall";
    case Sprite::path: return "path";
    case Sprite::transparent: return "transparent";
    case Sprite::player_look_down: return "player_look_down";
    case Sprite::player_look_down_sword: return "player_look_down_sword";
    case Sprite::player_look_left: return "player_look_left";
    case Sprite::player_look_left_sword: return "player_look_left_sword";
    case Sprite::player_look_right: return "player_look_right";
    case Sprite::player_look_right_sword: return "player_look_right_sword";
    case Sprite::player_look_up: return "player_look_up";
    case Sprite::player_look_up_sword: return "player_look_up_sword";
    case Sprite::player_walk_left1: return "player_walk_left1";
    case Sprite::player_walk_left2: return "player_walk_left2";
    case Sprite::player_walk_left_sword1: return "player_walk_left_sword1";
    case Sprite::player_walk_left_sword2: return "player_walk_left_sword2";
    case Sprite::player_walk_right1: return "player_walk_right1";
    case Sprite::player_walk_right2: return "player_walk_right2";
    case Sprite::player_walk_right_sword1: return "player_walk_right_sword1";
    case Sprite::player_walk_right_sword2: return "player_walk_right_sword2";
    case Sprite::player_walk_down1: return "player_walk_down1";
    case Sprite::player_walk_down2: return "player_walk_down2";
    case Sprite::player_walk_down_sword1: return "player_walk_down_sword1";
    case Sprite::player_walk_down_sword2: return "player_walk_down_sword2";
    case Sprite::player_walk_up1: return "player_walk_up1";
    case Sprite::player_walk_up2: return "player_walk_up2";
    case Sprite::player_walk_up_sword1: return "player_walk_up_sword1";
    case Sprite::player_walk_up_sword2: return "player_walk_up_sword2";
    case Sprite::player_won1: return "player_won1";
    case Sprite::player_won2: return "player_won2";
    case Sprite::fight_sword1: return "fight_sword1";
    case Sprite::fight_no_sword1: return "fight_no_sword1";
    case Sprite::fight2: return "fight2";
    case Sprite::fight3: return "fight3";
    case Sprite::fight4: return "fight4";
    case Sprite::fight_won1: return "fight_won1";
    case Sprite::fight_won2: return "fight_won2";
    case Sprite::fight_lost1: return "fight_lost1";
    case Sprite::fight_lost2: return "fight_lost2";
    case Sprite::enemy1: return "enemy1";
    case Sprite::enemy2: return "enemy2";
    case Sprite::prisoner1: return "prisoner1";
    case Sprite::prisoner2: return "prisoner2";
    case Sprite::sword: return "sword";
    case Sprite::exit: return "exit";
    case Sprite::n_sprites:
      assert(!"Should never use Sprite::n_sprites");
      throw std::logic_error("Never use Sprite::n_sprites");
  }
  assert(!"Should not get here");
  throw std::logic_error("Unknown Sprite");
}

 

 

 

 

 

./GameMaziak/qtmain.cpp

 

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#include <QApplication>

#include "qtmaziakmenudialog2.h"
#pragma GCC diagnostic pop

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);
  ribi::maziak::QtMaziakMenuDialog2 w;
  w.show();
  return a.exec();
}

 

 

 

 

 

./GameMaziak/qtmaziakcanvas.h

 

#ifndef QTMAZIAKCANVAS_H
#define QTMAZIAKCANVAS_H

#include "qtcanvas.h"

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include <boost/shared_ptr.hpp>
#pragma GCC diagnostic pop

struct QTimer;

namespace ribi {

struct TextCanvas;

namespace maziak {

struct MainDialog;

struct QtMaziakCanvas : public QtCanvas
{
  Q_OBJECT

public:

  QtMaziakCanvas(const int size);
  QtMaziakCanvas(const QtMaziakCanvas&) = delete;
  QtMaziakCanvas& operator=(const QtMaziakCanvas&) = delete;
  ~QtMaziakCanvas() noexcept;

  void keyPressEvent(QKeyEvent *e);
  void keyReleaseEvent(QKeyEvent *e);

private:
  const boost::shared_ptr<MainDialog> m_dialog;
  boost::shared_ptr<TextCanvas> m_text_canvas; //Same as Canvas
  const boost::shared_ptr<QTimer> m_timer_enemy;
  const boost::shared_ptr<QTimer> m_timer_press_key;
  const boost::shared_ptr<QTimer> m_timer_show_solution;
  const int m_view_height;
  const int m_view_width;

  static const boost::shared_ptr<Canvas> CreateCanvas(const int width, const int height) noexcept;
  static const boost::shared_ptr<MainDialog> CreateWidget(const int size) noexcept;

  void OnGameOver();
  void OnGameWon();
  void OnTimerStartShowingSolution();

private slots:
  void OnTimerPressKey();
  void OnTimerEnemy();
  void OnTimerStopShowingSolution();

};

} //~namespace maziak
} //~namespace ribi


#endif // QTMAZIAKCANVAS_H

 

 

 

 

 

./GameMaziak/qtmaziakcanvas.cpp

 

#include "qtmaziakcanvas.h"

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include <QKeyEvent>
#include <QTimer>

#include "qtcanvas.h"
#include "textcanvas.h"
#include "maziakmaindialog.h"
#pragma GCC diagnostic pop

ribi::maziak::QtMaziakCanvas::QtMaziakCanvas(
  const int size)
  : QtCanvas(CreateCanvas(size,size)),
    m_dialog(CreateWidget(size)),
    m_text_canvas{},
    m_timer_enemy(new QTimer),
    m_timer_press_key(new QTimer),
    m_timer_show_solution(new QTimer),
    m_view_height(9),
    m_view_width(9)
{
  m_text_canvas = boost::dynamic_pointer_cast<TextCanvas>(this->GetCanvas());
  assert(m_text_canvas);

  m_dialog->m_signal_game_over.connect(
    boost::bind(&ribi::maziak::QtMaziakCanvas::OnGameOver,this)
  );
  m_dialog->m_signal_game_won.connect(
    boost::bind(&ribi::maziak::QtMaziakCanvas::OnGameWon,this)
  );
  m_dialog->m_signal_start_showing_solution.connect(
    boost::bind(&ribi::maziak::QtMaziakCanvas::OnTimerStartShowingSolution,this)
  );

  m_timer_press_key->setInterval(100);
  m_timer_enemy->setInterval(1000);
  m_timer_show_solution->setInterval(5000);

  QObject::connect(m_timer_press_key.get(),&QTimer::timeout,
    this,&ribi::maziak::QtMaziakCanvas::OnTimerPressKey);
  QObject::connect(m_timer_enemy.get(),&QTimer::timeout,
    this,&ribi::maziak::QtMaziakCanvas::OnTimerEnemy);
  QObject::connect(m_timer_show_solution.get(),&QTimer::timeout,
    this,&ribi::maziak::QtMaziakCanvas::OnTimerStopShowingSolution);

  m_timer_press_key->start();
  m_timer_enemy->start();

  OnTimerPressKey();
}

ribi::maziak::QtMaziakCanvas::~QtMaziakCanvas() noexcept
{
  m_timer_enemy->stop();
  m_timer_press_key->stop();
  m_timer_show_solution->stop();
}

const boost::shared_ptr<ribi::Canvas> ribi::maziak::QtMaziakCanvas::CreateCanvas(
  const int width, const int height) noexcept
{
  const boost::shared_ptr<Canvas> canvas {
    new TextCanvas(width,height)
  };
  assert(canvas);
  return canvas;
}

const boost::shared_ptr<ribi::maziak::MainDialog> ribi::maziak::QtMaziakCanvas::CreateWidget(
  const int size) noexcept
{
  const boost::shared_ptr<MainDialog> w {
    new MainDialog(size)
  };
  return w;
}

void ribi::maziak::QtMaziakCanvas::keyPressEvent(QKeyEvent *e)
{
  switch(e->key())
  {
    case Qt::Key_Up: case Qt::Key_W:
      m_dialog->OnKeyPress(ribi::maziak::Key::up);
      break;
    case Qt::Key_Down: case Qt::Key_S:
      m_dialog->OnKeyPress(ribi::maziak::Key::down);
      break;
    case Qt::Key_Left: case Qt::Key_A:
      m_dialog->OnKeyPress(ribi::maziak::Key::left);
      break;
    case Qt::Key_Right: case Qt::Key_D:
      m_dialog->OnKeyPress(ribi::maziak::Key::right);
      break;
    case Qt::Key_Escape: case Qt::Key_Q:
      close();
  }
}

void ribi::maziak::QtMaziakCanvas::keyReleaseEvent(QKeyEvent *e)
{
  switch(e->key())
  {
    case Qt::Key_Up: case Qt::Key_W:
      m_dialog->OnKeyRelease(ribi::maziak::Key::up);
      break;
    case Qt::Key_Down: case Qt::Key_S:
      m_dialog->OnKeyRelease(ribi::maziak::Key::down);
      break;
    case Qt::Key_Left: case Qt::Key_A:
      m_dialog->OnKeyRelease(ribi::maziak::Key::left);
      break;
    case Qt::Key_Right: case Qt::Key_D:
      m_dialog->OnKeyRelease(ribi::maziak::Key::right);
      break;
  }
}

void ribi::maziak::QtMaziakCanvas::OnTimerPressKey()
{
  m_dialog->OnTimerPressKeys();
  m_dialog->AnimateFighting();
  m_dialog->RespondToCurrentSquare();
  SetCanvas(m_dialog->ToTextCanvas(m_view_width,m_view_height));
}

void ribi::maziak::QtMaziakCanvas::OnTimerEnemy()
{
  m_dialog->AnimateFighting();
  m_dialog->AnimateEnemiesAndPrisoners(m_view_width,m_view_height);
  SetCanvas(m_dialog->ToTextCanvas(m_view_width,m_view_height));
}

void ribi::maziak::QtMaziakCanvas::OnTimerStopShowingSolution()
{
  m_dialog->SetShowSolution(false);
  m_timer_show_solution->stop();
  SetCanvas(m_dialog->ToTextCanvas(m_view_width,m_view_height));
}

void ribi::maziak::QtMaziakCanvas::OnTimerStartShowingSolution()
{
  m_timer_show_solution->start();
  SetCanvas(m_dialog->ToTextCanvas(m_view_width,m_view_height));
}

void ribi::maziak::QtMaziakCanvas::OnGameOver()
{
  m_timer_press_key->stop();
  m_timer_enemy->stop();
  m_timer_show_solution->stop();
  //m_text_canvas->PutText(1,1,"GAME");
  //m_text_canvas->PutText(1,2,"OVER");
  //SetCanvas(m_text_canvas);
}

void ribi::maziak::QtMaziakCanvas::OnGameWon()
{
  m_timer_press_key->stop();
  m_timer_enemy->stop();
  m_timer_show_solution->stop();
  //m_text_canvas->PutText(1,1,"WELL");
  //m_text_canvas->PutText(1,2,"DONE");
  //SetCanvas(m_text_canvas);
}

 

 

 

 

 

./GameMaziak/qtmaziakgameoverdialog.h

 

//---------------------------------------------------------------------------
/*
Maziak, a simple maze game
Copyright (C) 2007-2014 Richel Bilderbeek

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/GameMaziak.htm
//---------------------------------------------------------------------------
#ifndef QTMAZIAKGAMEOVERDIALOG_H
#define QTMAZIAKGAMEOVERDIALOG_H

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include <boost/shared_ptr.hpp>
#include "qthideandshowdialog.h"
#pragma GCC diagnostic pop

struct QTimer;

namespace Ui {
  class QtMaziakGameOverDialog;
}

namespace ribi {

class QtMaziakGameOverDialog : public QtHideAndShowDialog
{
  Q_OBJECT

public:
  explicit QtMaziakGameOverDialog(QWidget *parent = 0);
  QtMaziakGameOverDialog(const QtMaziakGameOverDialog&) = delete;
  QtMaziakGameOverDialog& operator=(const QtMaziakGameOverDialog&) = delete;
  ~QtMaziakGameOverDialog() noexcept;

protected:
  void paintEvent(QPaintEvent*);
  void mousePressEvent(QMouseEvent*);
  void keyPressEvent(QKeyEvent*);

private:
  Ui::QtMaziakGameOverDialog *ui;
  boost::shared_ptr<QTimer> m_timer;
  bool m_allow_close;

  private slots:
  void onTimer();

};

} //~namespace ribi

#endif // QTMAZIAKGAMEOVERDIALOG_H

 

 

 

 

 

./GameMaziak/qtmaziakgameoverdialog.cpp

 

//---------------------------------------------------------------------------
/*
Maziak, a simple maze game
Copyright (C) 2007-2014 Richel Bilderbeek

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/GameMaziak.htm
//---------------------------------------------------------------------------
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include "qtmaziakgameoverdialog.h"

#include <cassert>

#include <boost/timer.hpp>
#include <QPainter>
#include <QPaintEvent>
#include <QTimer>

#include "ui_qtmaziakgameoverdialog.h"
#pragma GCC diagnostic pop

ribi::QtMaziakGameOverDialog::QtMaziakGameOverDialog(QWidget *parent) :
  QtHideAndShowDialog(parent),
  ui(new Ui::QtMaziakGameOverDialog),
  m_timer(new QTimer),
  m_allow_close(false)
{
  ui->setupUi(this);
  m_timer->setInterval(2500);
  QObject::connect(
    m_timer.get(),&QTimer::timeout,
    this,&ribi::QtMaziakGameOverDialog::onTimer
  );
  m_timer->start();
}

ribi::QtMaziakGameOverDialog::~QtMaziakGameOverDialog() noexcept
{
  delete ui;
}

void ribi::QtMaziakGameOverDialog::onTimer()
{
  m_allow_close = true;
  m_timer->stop();
}

void ribi::QtMaziakGameOverDialog::paintEvent(QPaintEvent*)
{
  QPainter painter(this);
  {
    //Top
    QPixmap pixmap(":/images/GameOver.png");
    assert(!pixmap.isNull());
    painter.drawPixmap(ui->widget_top->geometry(),pixmap);
  }
  {
    //Center
    QPixmap pixmap(":/images/Rip.png");
    assert(!pixmap.isNull());
    painter.drawPixmap(ui->widget_center->geometry(),pixmap);
  }
  {
    //Bottom
    QPixmap pixmap(":/images/GameOver.png");
    assert(!pixmap.isNull());
    painter.drawPixmap(ui->widget_bottom->geometry(),pixmap);
  }
}

void ribi::QtMaziakGameOverDialog::mousePressEvent(QMouseEvent*)
{
  if (m_allow_close) close();
}

void ribi::QtMaziakGameOverDialog::keyPressEvent(QKeyEvent*)
{
  if (m_allow_close) close();
}

 

 

 

 

 

./GameMaziak/qtmaziakgamewondialog.h

 

//---------------------------------------------------------------------------
/*
Maziak, a simple maze game
Copyright (C) 2007-2014 Richel Bilderbeek

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/GameMaziak.htm
//---------------------------------------------------------------------------
#ifndef QTMAZIAKGAMEWONDIALOG_H
#define QTMAZIAKGAMEWONDIALOG_H

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include <boost/shared_ptr.hpp>
#include "qthideandshowdialog.h"
#pragma GCC diagnostic pop

struct QTimer;

namespace Ui {
  class QtMaziakGameWonDialog;
}

namespace ribi {

class QtMaziakGameWonDialog : public QtHideAndShowDialog
{
  Q_OBJECT

public:
  explicit QtMaziakGameWonDialog(QWidget *parent = 0);
  QtMaziakGameWonDialog(const QtMaziakGameWonDialog&) = delete;
  QtMaziakGameWonDialog& operator=(const QtMaziakGameWonDialog&) = delete;
  ~QtMaziakGameWonDialog() noexcept;

protected:
  void paintEvent(QPaintEvent*);
  void mousePressEvent(QMouseEvent*);
  void keyPressEvent(QKeyEvent*);

private:
  Ui::QtMaziakGameWonDialog *ui;
  boost::shared_ptr<QTimer> m_timer;
  bool m_allow_close;

  private slots:
  void onTimer();
};

} //~namespace ribi

#endif // QTMAZIAKGAMEWONDIALOG_H

 

 

 

 

 

./GameMaziak/qtmaziakgamewondialog.cpp

 

//---------------------------------------------------------------------------
/*
Maziak, a simple maze game
Copyright (C) 2007-2014 Richel Bilderbeek

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/GameMaziak.htm
//---------------------------------------------------------------------------
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include "qtmaziakgamewondialog.h"

#include <cassert>
#include <iostream>

#include <boost/timer.hpp>

#include <QPainter>
#include <QPaintEvent>
#include <QTimer>

#include "ui_qtmaziakgamewondialog.h"

#pragma GCC diagnostic pop

ribi::QtMaziakGameWonDialog::QtMaziakGameWonDialog(QWidget *parent) :
  QtHideAndShowDialog(parent),
  ui(new Ui::QtMaziakGameWonDialog),
  m_timer(new QTimer),
  m_allow_close(false)
{
  ui->setupUi(this);

  m_timer->setInterval(2500);
  QObject::connect(m_timer.get(),&QTimer::timeout,
    this,&ribi::QtMaziakGameWonDialog::onTimer
  );
  m_timer->start();
}

ribi::QtMaziakGameWonDialog::~QtMaziakGameWonDialog() noexcept
{
  delete ui;
}

void ribi::QtMaziakGameWonDialog::onTimer()
{
  m_allow_close = true;
  m_timer->stop();
}

void ribi::QtMaziakGameWonDialog::paintEvent(QPaintEvent*)
{
  QPainter painter(this);
  {
    //Top
    QPixmap pixmap(":/images/Congratulations.png");
    assert(!pixmap.isNull());
    painter.drawPixmap(ui->widget_top->geometry(),pixmap);
  }
  {
    //Center
    QPixmap pixmap(":/images/PlayerWon1.png");
    assert(!pixmap.isNull());
    painter.drawPixmap(ui->widget_center->geometry(),pixmap);
  }
  {
    //Bottom
    QPixmap pixmap(":/images/Congratulations.png");
    assert(!pixmap.isNull());
    painter.drawPixmap(ui->widget_bottom->geometry(),pixmap);
  }
}

void ribi::QtMaziakGameWonDialog::mousePressEvent(QMouseEvent*)
{
  if (m_allow_close) close();
}

void ribi::QtMaziakGameWonDialog::keyPressEvent(QKeyEvent*)
{
  if (m_allow_close) close();
}

 

 

 

 

 

./GameMaziak/qtmaziakinstructionsdialog.h

 

//---------------------------------------------------------------------------
/*
Maziak, a simple maze game
Copyright (C) 2007-2014 Richel Bilderbeek

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/GameMaziak.htm
//---------------------------------------------------------------------------
#ifndef QTMAZIAKINSTRUCTIONSDIALOG_H
#define QTMAZIAKINSTRUCTIONSDIALOG_H

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include "qthideandshowdialog.h"
#pragma GCC diagnostic pop

namespace Ui {
    class QtMaziakInstructionsDialog;
}

namespace ribi {

class QtMaziakInstructionsDialog : public QtHideAndShowDialog
{
    Q_OBJECT

public:
    explicit QtMaziakInstructionsDialog(QWidget *parent = 0);
    QtMaziakInstructionsDialog(const QtMaziakInstructionsDialog&) = delete;
    QtMaziakInstructionsDialog& operator=(const QtMaziakInstructionsDialog&) = delete;
    ~QtMaziakInstructionsDialog() noexcept;

private:
    Ui::QtMaziakInstructionsDialog *ui;
};

} //~namespace ribi

#endif // QTMAZIAKINSTRUCTIONSDIALOG_H

 

 

 

 

 

./GameMaziak/qtmaziakinstructionsdialog.cpp

 

//---------------------------------------------------------------------------
/*
Maziak, a simple maze game
Copyright (C) 2007-2014 Richel Bilderbeek

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/GameMaziak.htm
//---------------------------------------------------------------------------
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"

#include "qtmaziakinstructionsdialog.h"
#include "ui_qtmaziakinstructionsdialog.h"

#pragma GCC diagnostic pop

ribi::QtMaziakInstructionsDialog::QtMaziakInstructionsDialog(QWidget *parent) :
    QtHideAndShowDialog(parent),
    ui(new Ui::QtMaziakInstructionsDialog)
{
    ui->setupUi(this);
}

ribi::QtMaziakInstructionsDialog::~QtMaziakInstructionsDialog() noexcept
{
    delete ui;
}

 

 

 

 

 

./GameMaziak/qtmaziakmaindialog.h

 

//---------------------------------------------------------------------------
/*
Maziak, a simple maze game
Copyright (C) 2007-2014 Richel Bilderbeek

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/GameMaziak.htm
//---------------------------------------------------------------------------
#ifndef QTMAZIAKMAINDIALOG_H
#define QTMAZIAKMAINDIALOG_H

#include <cassert>
#include <map>
#include <vector>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include <boost/shared_ptr.hpp>
#include "qthideandshowdialog.h"
#include "maziakmazesquare.h"
#include "maziaksprite.h"
#include "maziakfwd.h"
#include "maziakkey.h"
#include "maziakplayerdirection.h"
#include "maziakplayermove.h"
#pragma GCC diagnostic pop

struct QPixmap;
struct QTimer;

namespace Ui {
  class QtMaziakMainDialog;
}


namespace ribi {
namespace maziak {


class QtMaziakMainDialog : public QtHideAndShowDialog
{
  Q_OBJECT

public:

  explicit QtMaziakMainDialog(const int maze_size, QWidget *parent = 0);
  QtMaziakMainDialog(const QtMaziakMainDialog&) = delete;
  QtMaziakMainDialog& operator=(const QtMaziakMainDialog&) = delete;
  ~QtMaziakMainDialog() noexcept;

private:
  Ui::QtMaziakMainDialog *ui;

  typedef unsigned int WORD;

  boost::shared_ptr<MainDialog> m_dialog;
  std::map<WORD,Key> m_keys;

  const boost::shared_ptr<const Sprites> m_sprites;
  const boost::shared_ptr<QTimer> m_timer_enemy;
  const boost::shared_ptr<QTimer> m_timer_press_key;
  const boost::shared_ptr<QTimer> m_timer_show_solution;
  const int m_view_height;
  const int m_view_width;

  static const std::map<WORD,Key> CreateDefaultKeys() noexcept;
  void OnGameOver();
  void OnGameWon();
  void OnTimerStartShowingSolution();

  void resizeEvent(QResizeEvent*);
  void keyPressEvent(QKeyEvent * e);
  void keyReleaseEvent(QKeyEvent * e);
  void paintEvent(QPaintEvent * event);

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif

private slots:
  void OnTimerPressKey();
  void OnTimerEnemy();
  void OnTimerStopShowingSolution();
};

} //~namespace maziak
} //~namespace ribi

#endif // QTMAZIAKMAINDIALOG_H

 

 

 

 

 

./GameMaziak/qtmaziakmaindialog.cpp

 

//---------------------------------------------------------------------------
/*
Maziak, a simple maze game
Copyright (C) 2007-2014 Richel Bilderbeek

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/GameMaziak.htm
//---------------------------------------------------------------------------
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#include "qtmaziakmaindialog.h"

#include <algorithm>
#include <cassert>
#include <cmath>

#include <iostream>
#include <stdexcept>
#include <vector>

#include <boost/scoped_ptr.hpp>

#include <QDesktopWidget>
#include <QKeyEvent>
#include <QPainter>
#include <QTimer>
#include "maziakhelper.h"
#include "maziakintmaze.h"
#include "maziakmaze.h"
#include "maziaksprites.h"
#include "qtmaziakgameoverdialog.h"
#include "testtimer.h"
#include "qtmaziakgamewondialog.h"
#include "maziaksolutionmaze.h"
#include "maziakmaindialog.h"
#include "ui_qtmaziakmaindialog.h"
#include "trace.h"

#pragma GCC diagnostic pop

ribi::maziak::QtMaziakMainDialog::QtMaziakMainDialog(
  const int maze_size,
  QWidget *parent
)
  : QtHideAndShowDialog(parent),
    ui(new Ui::QtMaziakMainDialog),
    m_dialog{new MainDialog(maze_size)},
    m_keys{},
    m_sprites(new Sprites),
    m_timer_enemy(new QTimer),
    m_timer_press_key(new QTimer),
    m_timer_show_solution(new QTimer),
    m_view_height(9),
    m_view_width(9)
{
  #ifndef NDEBUG
  Test();
  #endif
  ui->setupUi(this);

  m_dialog->m_signal_game_over.connect(
    boost::bind(&ribi::maziak::QtMaziakMainDialog::OnGameOver,this)
  );
  m_dialog->m_signal_game_won.connect(
    boost::bind(&ribi::maziak::QtMaziakMainDialog::OnGameWon,this)
  );
  m_dialog->m_signal_start_showing_solution.connect(
    boost::bind(&ribi::maziak::QtMaziakMainDialog::OnTimerStartShowingSolution,this)
  );

  assert(maze_size && "Maze size must be 7 + (4 * n) for n e [0,->>");
  assert(m_dialog->GetMaze()->IsSquare());

  m_timer_press_key->setInterval(100);
  m_timer_enemy->setInterval(1000);
  m_timer_show_solution->setInterval(5000);

  QObject::connect(m_timer_press_key.get(),&QTimer::timeout,
    this,&ribi::maziak::QtMaziakMainDialog::OnTimerPressKey);
  QObject::connect(m_timer_enemy.get(),&QTimer::timeout,
    this,&ribi::maziak::QtMaziakMainDialog::OnTimerEnemy);
  QObject::connect(m_timer_show_solution.get(),&QTimer::timeout,
    this,&ribi::maziak::QtMaziakMainDialog::OnTimerStopShowingSolution);

  m_timer_press_key->start();
  m_timer_enemy->start();

  //Put the dialog in the screen center at 75% of fullscreen size
  const QRect screen = QApplication::desktop()->screenGeometry();
  this->setGeometry(0,0,screen.width() * 75 / 100,screen.height() * 75 / 100);
  this->move( screen.center() - this->rect().center() );
}

ribi::maziak::QtMaziakMainDialog::~QtMaziakMainDialog() noexcept
{
  delete ui;
}

const std::map<ribi::maziak::QtMaziakMainDialog::WORD,ribi::maziak::Key> ribi::maziak::QtMaziakMainDialog::CreateDefaultKeys() noexcept
{
  std::map<WORD,Key> m;
  m.insert(std::make_pair(Qt::Key_Up   ,Key::up   ));
  m.insert(std::make_pair(Qt::Key_Right,Key::right));
  m.insert(std::make_pair(Qt::Key_Down ,Key::down ));
  m.insert(std::make_pair(Qt::Key_Left ,Key::left ));
  return m;
}

void ribi::maziak::QtMaziakMainDialog::resizeEvent(QResizeEvent*)
{
  this->repaint();
}

void ribi::maziak::QtMaziakMainDialog::keyPressEvent(QKeyEvent* e)
{
  switch (e->key())
  {
    case Qt::Key_Left : m_dialog->OnKeyPress(Key::left); break;
    case Qt::Key_Right: m_dialog->OnKeyPress(Key::right); break;
    case Qt::Key_Up   : m_dialog->OnKeyPress(Key::up); break;
    case Qt::Key_Down : m_dialog->OnKeyPress(Key::down); break;
    case Qt::Key_F1   : OnGameOver(); close(); break;
    case Qt::Key_F2   : OnGameWon(); close(); break;
    case Qt::Key_Escape: close(); break;
  }
}

void ribi::maziak::QtMaziakMainDialog::keyReleaseEvent(QKeyEvent * e)
{
  switch (e->key())
  {
    case Qt::Key_Left : m_dialog->OnKeyRelease(Key::left); break;
    case Qt::Key_Right: m_dialog->OnKeyRelease(Key::right); break;
    case Qt::Key_Up   : m_dialog->OnKeyRelease(Key::up); break;
    case Qt::Key_Down : m_dialog->OnKeyRelease(Key::down); break;
  }
}

void ribi::maziak::QtMaziakMainDialog::OnTimerPressKey()
{
  m_dialog->OnTimerPressKeys();
  repaint();
}

void ribi::maziak::QtMaziakMainDialog::OnTimerEnemy()
{
  m_dialog->AnimateEnemiesAndPrisoners(m_view_width,m_view_height);
  repaint();
}

void ribi::maziak::QtMaziakMainDialog::OnTimerStopShowingSolution()
{
  m_dialog->SetShowSolution(false);
  m_timer_show_solution->stop();
}

void ribi::maziak::QtMaziakMainDialog::OnTimerStartShowingSolution()
{
  m_timer_show_solution->start();
}

void ribi::maziak::QtMaziakMainDialog::paintEvent(QPaintEvent *)
{
  //const int block_width  = 1 + ((ui->widget->width()  - 4) / m_view_width);
  //const int block_height = 1 + ((ui->widget->height() - 4) / m_view_height);
  const int block_width  = width()  / m_view_width;
  const int block_height = height() / m_view_height;

  m_dialog->AnimateFighting();

  //Player-environment interactions
  QPainter painter(this);
  assert(painter.isActive());

  //Clean painter
  //?Really needed?
  /*
  {
    const boost::shared_ptr<const QPixmap> temp { m_sprites->Get(Sprite::empty) };

    assert(temp);
    painter.drawPixmap(ui->widget->rect(),*temp);
  }
  */

  m_dialog->RespondToCurrentSquare();

  //Draw maze
  {
    for (int y=0; y!=m_view_height; ++y)
    {
      for (int x=0; x!=m_view_width; ++x)
      {
        //xVector and yVector are the indices in the non-visual maze 2D std::vector
        const int xVector = m_dialog->GetX() - (m_view_width  / 2) + x;
        const int yVector = m_dialog->GetY() - (m_view_height / 2) + y;
        //Draw the floor tile
        const boost::shared_ptr<const QPixmap> pixmap_floor {
          m_sprites->Get(
            m_dialog->GetSpriteFloor(
              xVector,
              yVector
            )
          )
        };
        assert(pixmap_floor);
        painter.drawPixmap(
          (x * block_width )+0,
          (y * block_height)+0,
          block_width,
          block_height,
          *pixmap_floor);
        //Draw what's moving or standing on the floor
        const auto pixmap_above_floor(
          m_sprites->Get(
            m_dialog->GetSpriteAboveFloor(
              xVector,
              yVector
            )
          )
        );
        assert(pixmap_above_floor);
        painter.drawPixmap(
          (x * block_width )+0,
          (y * block_height)+0,
          block_width,
          block_height,
          *pixmap_above_floor
        );
      }
    }
  }

  //Draw player
  {
    const boost::shared_ptr<const QPixmap> player {
      m_sprites->Get(
        m_dialog->GetSpritePlayer()
      )
    };
    assert(player);
    painter.drawPixmap(
      ((m_view_width  / 2) * block_width )+0,
      ((m_view_height / 2) * block_height)+0,
       block_width,
       block_height,
       *player
     );
  }
}

void ribi::maziak::QtMaziakMainDialog::OnGameOver()
{
  m_timer_press_key->stop();
  m_timer_enemy->stop();
  m_timer_show_solution->stop();
  this->hide();
  boost::scoped_ptr<QtMaziakGameOverDialog> f(new QtMaziakGameOverDialog(0));
  f->exec();
  close();
}

void ribi::maziak::QtMaziakMainDialog::OnGameWon()
{
  m_timer_press_key->stop();
  m_timer_enemy->stop();
  m_timer_show_solution->stop();
  this->hide();
  boost::scoped_ptr<QtMaziakGameWonDialog> f(new QtMaziakGameWonDialog);
  this->hide();
  f->exec();
  close();
}




#ifndef NDEBUG
void ribi::maziak::QtMaziakMainDialog::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  QtMaziakMainDialog(99);
  maziak::MainDialog(7);
  const TestTimer test_timer(__func__,__FILE__,1.0);
}
#endif

 

 

 

 

 

./GameMaziak/qtmaziakmenudialog2.h

 

//---------------------------------------------------------------------------
/*
Maziak, a simple maze game
Copyright (C) 2007-2014 Richel Bilderbeek

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/GameMaziak.htm
//---------------------------------------------------------------------------
#ifndef QTMAZIAKMENUDIALOG2_H
#define QTMAZIAKMENUDIALOG2_H

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#include "qthideandshowdialog.h"
#include "maziakdifficulty.h"
#pragma GCC diagnostic pop

struct QKeyPressEvent;
struct QMouseEvent;
struct QPaintEvent;

namespace Ui {
  class QtMaziakMenuDialog2;
}

namespace ribi {
namespace maziak {

class QtMaziakMenuDialog2 : public QtHideAndShowDialog
{
  Q_OBJECT

public:
  explicit QtMaziakMenuDialog2(QWidget *parent = 0);
  QtMaziakMenuDialog2(const QtMaziakMenuDialog2&) = delete;
  QtMaziakMenuDialog2& operator=(const QtMaziakMenuDialog2&) = delete;
  ~QtMaziakMenuDialog2() noexcept;

private:
  Ui::QtMaziakMenuDialog2 *ui;
  int GetMazeSize() const;
  Difficulty m_difficulty;
  void keyPressEvent(QKeyEvent * event);
  void mousePressEvent(QMouseEvent * event);
  void paintEvent(QPaintEvent*);
  void OnStart();
  void OnStartRetro();
  void OnInstructions();
  void OnAbout();

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif
};

} //~namespace maziak
} //~namespace ribi

#endif // QTMAZIAKMENUDIALOG2_H

 

 

 

 

 

./GameMaziak/qtmaziakmenudialog2.cpp

 

//---------------------------------------------------------------------------
/*
Maziak, a simple maze game
Copyright (C) 2007-2014 Richel Bilderbeek

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/GameMaziak.htm
//---------------------------------------------------------------------------
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include "qtmaziakmenudialog2.h"

#include <cassert>
#include <iostream>
#include <stdexcept>

#include <boost/scoped_ptr.hpp>

#include <QDesktopWidget>
#include <QKeyEvent>
#include <QPainter>
#include <QMouseEvent>

#include "about.h"
#include "maziakmenudialog.h"
#include "qtaboutdialog.h"
#include "qtcanvas.h"
#include "qtcanvasdialog.h"
#include "testtimer.h"
#include "qtmaziakcanvas.h"
#include "qtmaziakinstructionsdialog.h"
#include "qtmaziakmaindialog.h"
#include "trace.h"
#include "ui_qtmaziakmenudialog2.h"

#pragma GCC diagnostic pop

ribi::maziak::QtMaziakMenuDialog2::QtMaziakMenuDialog2(QWidget *parent) :
    QtHideAndShowDialog(parent),
    ui(new Ui::QtMaziakMenuDialog2),
    m_difficulty(Difficulty::easy)
{
  #ifndef NDEBUG
  Test();
  #endif
  ui->setupUi(this);

  //Put the dialog in the screen's center
  const QRect screen = QApplication::desktop()->screenGeometry();
  this->move( screen.center() - this->rect().center() );
}

ribi::maziak::QtMaziakMenuDialog2::~QtMaziakMenuDialog2() noexcept
{
  delete ui;
}

void ribi::maziak::QtMaziakMenuDialog2::mousePressEvent(QMouseEvent * event)
{
  if (ui->widget_easy->geometry().contains(
    event->x(), event->y()))
  {
    m_difficulty = Difficulty::easy;
    repaint();
    return;
  }
  if (ui->widget_medium->geometry().contains(
    event->x(), event->y()))
  {
    m_difficulty = Difficulty::medium;
    repaint();
    return;
  }
  if (ui->widget_hard->geometry().contains(
    event->x(), event->y()))
  {
    m_difficulty = Difficulty::hard;
    repaint();
    return;
  }
  if (ui->widget_start->geometry().contains(
    event->x(), event->y()))
  {
    OnStart(); return;
  }
  if (ui->widget_start_retro->geometry().contains(
    event->x(), event->y()))
  {
    OnStartRetro(); return;
  }
  if (ui->widget_instructions->geometry().contains(
    event->x(), event->y()))
  {
    OnInstructions();
    return;
  }
  if (ui->widget_about->geometry().contains(
    event->x(), event->y()))
  {
    OnAbout();
    return;
  }
  if (ui->widget_quit->geometry().contains(
    event->x(), event->y()))
  {
    close();
  }
}

void ribi::maziak::QtMaziakMenuDialog2::keyPressEvent(QKeyEvent * event)
{
  switch (event->key())
  {
    case Qt::Key_Up: case Qt::Key_Left:
    {
      switch (m_difficulty)
      {
        case Difficulty::easy: return;
        case Difficulty::medium: m_difficulty = Difficulty::easy; repaint(); return;
        case Difficulty::hard: m_difficulty = Difficulty::medium; repaint(); return;
        default: assert(!"Should not get here");
      }
    }
    case Qt::Key_Down: case Qt::Key_Right:
    {
      switch (m_difficulty)
      {
        case Difficulty::easy: m_difficulty = Difficulty::medium; repaint(); return;
        case Difficulty::medium: m_difficulty = Difficulty::hard; repaint(); return;
        case Difficulty::hard: return;
        default: assert(!"Should not get here");
      }
    }
    case Qt::Key_S: OnStart(); break;
    case Qt::Key_I: OnInstructions(); break;
    case Qt::Key_A: OnAbout(); break;
    case Qt::Key_Q:
    case Qt::Key_Escape:
      close(); return;
    default:
      break;
  }
}

void ribi::maziak::QtMaziakMenuDialog2::paintEvent(QPaintEvent*)
{
  QPainter painter(this);
  {
    QPixmap background(":/images/GameMaziakBackground.png");
    painter.drawPixmap(rect(),background);
  }

  {
    //Top left
    QPixmap pixmap;
    switch (m_difficulty)
    {
      case Difficulty::easy:
        pixmap = QPixmap(":/images/PlayerWon1.png");
        break;
      case Difficulty::medium:
        pixmap = QPixmap(":/images/PlayerLookDown.png");
        break;
      case Difficulty::hard:
        pixmap = QPixmap(":/images/PlayerScared.png");
        break;
      default:
        assert(!"Should not get here");
    }
    assert(!pixmap.isNull());
    painter.drawPixmap(ui->widget_top_left->geometry(),pixmap);
  }
  {
    //Top right
    QPixmap pixmap;
    switch (m_difficulty)
    {
      case Difficulty::easy:
        pixmap = QPixmap(":/images/Fight2.png");
        break;
      case Difficulty::medium:
        pixmap = QPixmap(":/images/Fight3.png");
        break;
      case Difficulty::hard:
        pixmap = QPixmap(":/images/Fight4.png");
        break;
      default:
        assert(!"Should not get here");
    }
    assert(!pixmap.isNull());
    painter.drawPixmap(ui->widget_top_right->geometry(),pixmap);
  }
  {
    //Easy
    QPixmap pixmap(m_difficulty == Difficulty::easy
      ? ":/images/Easy_selected.png"
      : ":/images/Easy_not_selected.png");
    assert(!pixmap.isNull());
    painter.drawPixmap(ui->widget_easy->geometry(),pixmap);
  }
  {
    //Medium
    QPixmap pixmap(m_difficulty == Difficulty::medium
      ? ":/images/Medium_selected.png"
      : ":/images/Medium_not_selected.png");
    assert(!pixmap.isNull());

    painter.drawPixmap(ui->widget_medium->geometry(),pixmap);
  }
  {
    //Hard
    QPixmap pixmap(m_difficulty == Difficulty::hard
      ? ":/images/Hard_selected.png"
      : ":/images/Hard_not_selected.png");
    assert(!pixmap.isNull());
    painter.drawPixmap(ui->widget_hard->geometry(),pixmap);
  }
  {
    //Start
    QPixmap pixmap(":/images/Start.png");
    assert(!pixmap.isNull());
    painter.drawPixmap(ui->widget_start->geometry(),pixmap);
  }
  {
    //Instructions
    QPixmap pixmap(":/images/Instructions.png");
    assert(!pixmap.isNull());
    painter.drawPixmap(ui->widget_instructions->geometry(),pixmap);
  }
  {
    //About
    QPixmap pixmap(":/images/About.png");
    assert(!pixmap.isNull());
    painter.drawPixmap(ui->widget_about->geometry(),pixmap);
  }
  {
    //Quit
    QPixmap pixmap(":/images/Quit.png");
    assert(!pixmap.isNull());
    painter.drawPixmap(ui->widget_quit->geometry(),pixmap);
  }


}

int ribi::maziak::QtMaziakMenuDialog2::GetMazeSize() const
{
  switch (m_difficulty)
  {
    case Difficulty::easy  : return  99;
    case Difficulty::medium: return 499;
    case Difficulty::hard  : return 999;
  }
  assert(!"Should not get here");
  throw std::logic_error("Unsupported value of mDifficulty");
}

void ribi::maziak::QtMaziakMenuDialog2::OnAbout()
{
  About a = MenuDialog().GetAbout();
  boost::scoped_ptr<QtAboutDialog> d(new QtAboutDialog(a));
  this->ShowChild(d.get());
}

void ribi::maziak::QtMaziakMenuDialog2::OnInstructions()
{
  boost::scoped_ptr<QtMaziakInstructionsDialog> d(new QtMaziakInstructionsDialog);
  this->ShowChild(d.get());
}

void ribi::maziak::QtMaziakMenuDialog2::OnStart()
{
  boost::scoped_ptr<QtMaziakMainDialog> d(new QtMaziakMainDialog(GetMazeSize()));
  this->ShowChild(d.get());
}

void ribi::maziak::QtMaziakMenuDialog2::OnStartRetro()
{
  QtCanvas * const qtcanvas {
    new QtMaziakCanvas(GetMazeSize())
  };
  boost::scoped_ptr<QtCanvasDialog> d {
    new QtCanvasDialog(qtcanvas)
  };
  {
    //Put the dialog in the screen center
    const QRect screen = QApplication::desktop()->screenGeometry();
    d->setGeometry(
      0,0,256,256);
    d->move( screen.center() - this->rect().center() );
  }
  d->setWindowTitle("Maziak");
  ShowChild(d.get());
}

#ifndef NDEBUG
void ribi::maziak::QtMaziakMenuDialog2::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  maziak::MenuDialog();
  {
    const boost::scoped_ptr<QtMaziakMainDialog> d(new QtMaziakMainDialog(7));
    assert(d);
  }
  {
    const boost::scoped_ptr<QtMaziakInstructionsDialog> d(new QtMaziakInstructionsDialog);
    assert(d);
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
}
#endif

 

 

 

 

 

Go back to Richel Bilderbeek's C++ page.

Go back to Richel Bilderbeek's homepage.

 

Valid XHTML 1.0 Strict

This page has been created by the tool CodeToHtml