Rose
ConwayLife.h
Go to the documentation of this file.
1 
8 #pragma once
9 
10 #include <array>
11 #include <exception>
12 #include <memory>
13 #include <mutex>
14 #include "Constants.h"
15 #include "ScreenMetrics.h"
16 #include "Rose.h"
17 #include "Signals.h"
18 #include "Slider.h"
19 #include "Timer.h"
20 
21 static constexpr size_t ScreenWidth = 800;
22 static constexpr size_t ScreenHeight = 480;
23 static constexpr size_t PixelSize = 5;
24 static constexpr size_t BoardWidth = ScreenWidth / PixelSize;
25 static constexpr size_t BoardHeight = ScreenHeight / PixelSize;
26 
34 };
35 
36 struct StartPattern {
38  size_t pixelSize;
43  std::string_view data;
44 };
45 
46 static StartPattern Switch1 = {
47  TopLeft, 6, rose::Size{400,240}, rose::Position {350,200},
48  rose::Position {0,0}, rose::Position{0,0},
49  "1: 7; 2: 5 7 8; 3: 5 7; 4: 5; 5: 3; 6: 1 3;"
50 };
51 
52 static StartPattern Switch2 = {
53  TopLeft, 6, rose::Size{400,240}, rose::Position { 350, 200},
54  rose::Position { 0, 0}, rose::Position{0,0},
55  "1: 1 2 3 5; 2: 1; 3: 4 5; 4: 2 3 5; 5: 1 3 5;"
56 };
57 
58 static StartPattern Acorn = {
59  Center, 6, rose::Size{400, 240}, rose::Position{0, 0},
60  rose::Position{0, 0}, rose::Position{0, 0},
61  "1:2; 2:4; 3:1 2 5 6 7;"
62 };
63 
64 static StartPattern GosperGliderGun = {
65  TopLeft, 10, rose::Size{100, 50}, rose::Position{0, 0},
66  rose::Position{0, 0}, rose::Position{0, 0},
67  "1:25; 2:23 25; 3:13 14 21 22 35 36; 4:12 16 21 22 35 36; 5:1 2 11 17 21 22;"
68  "6:1 2 11 15 17 18 23 25; 7:11 17 25; 8:12 16; 9:13 14;"
69 };
70 
71 static StartPattern Tribute = {
72  TopLeft, 10, rose::Size{80, 50}, rose::Position{ 5, 38},
73  rose::Position{0, 0}, rose::Position{0, 0},
74  "1:3 4 5; 2:3 5; 3:3 5; 4:4; 5:1 3 4 5; 6: 2 4 6; 7:5; 8:3 5; 9:3 5;"
75 };
76 
80 enum State {
81  Dead,
82  Live,
84  Born,
85 };
86 
87 struct Cell {
88  State state{Dead};
89  uint32_t age{};
90 
91  void setState(State newState) { state = newState; age = 0; }
92 };
93 
94 class Board : public rose::Widget {
95 protected:
96  std::mutex boardLock{};
97  rose::SignalSerialNumber mSignalSerialNumber{};
98 
99  std::unique_ptr<Cell[]> board{};
100  size_t mBoardWidth{}, mBoardHeight{}, mCellPixels{}, mArrayLen{}, mGeneration{};
101 
102  Cell& at(size_t x, size_t y) {
103  size_t l = y * mBoardWidth + x;
104  if (l < mArrayLen)
105  return board.get()[l];
106  else
107  throw std::range_error("Board co-ordinates out of range.");
108  }
109 
110  Cell& check(size_t x, size_t y) {
111  if (x < mBoardWidth && y < mBoardHeight)
112  return at(x,y);
113  else
114  throw std::range_error("Board co-ordinates out of range.");
115  }
116 
117 public:
118  Board() = default;
119 
120  Board(size_t screenWidth, size_t screenHeight, size_t cellSize, size_t boardWidth, size_t boardHeight);
121 
122  ~Board() override = default;
123 
124  void initialize(StartPattern &startPattern);
125 
126  void reInitialize(StartPattern &startPattern);
127 
128  void initializeComposite() override;
129 
130  rose::Rectangle widgetLayout(rose::sdl::Renderer &renderer, rose::Rectangle available, uint layoutStage) override {
131  return rose::Rectangle{0, 0, (int)(mBoardWidth * mCellPixels), (int)(mBoardHeight * mCellPixels)};
132  }
133 
134  void draw(rose::sdl::Renderer &renderer, rose::Rectangle parentRect) override;
135 
136  void generation();
137 
138  size_t countCell(int x, int y);
139 
140  std::shared_ptr<rose::Slot<uint32_t>> mTimerRx;
141 
142  rose::Signal<std::string> mGenCountTx;
143 
144  rose::Position getCenter() const { return rose::Position{(int)mBoardWidth / 2, (int)mBoardHeight / 2}; }
145 };
146 
157 };
158 
159 class ConwayLife : public rose::Rose {
160 protected:
161 
162  rose::Timer mTimer;
163 
164  StartPattern& mStartPattern{GosperGliderGun};
165 
166  std::shared_ptr<rose::Button> mExit{},
167  mAcorn{},
168  mGun{},
169  mSwitch1{},
170  mSwitch2{},
171  mTribute{};
172 
173  std::shared_ptr<rose::Label> mGeneration{};
174  std::shared_ptr<rose::Slider> mSlider{};
175 
176 public:
177  std::shared_ptr<rose::Slot<rose::Button::SignalType>> mButtonRx;
178  std::shared_ptr<rose::Slot<rose::Slider::SignalType>> mRateRx;
179 
180  std::shared_ptr<Board> mBoard{};
181 
182  ConwayLife() = delete;
183 
184  ~ConwayLife() override = default;
185 
186  ConwayLife(int argc, char **argv, const std::string_view title) : rose::Rose(rose::Size{800, 480},
187  argc, argv, title), mTimer(1000) {
188  if (mCmdLineParser.cmdOptionExists("-rate")) {
189  mTimer.setInterval(std::strtoul(mCmdLineParser.getCmdOption("-rate").c_str(), nullptr, 10));
190  }
191 
192  if (mCmdLineParser.cmdOptionExists("-pattern")) {
193  auto pattern = mCmdLineParser.getCmdOption("-pattern");
194  if (pattern == "gun")
195  mStartPattern = GosperGliderGun;
196  else if (pattern == "acorn")
197  mStartPattern = Acorn;
198  else if (pattern == "switch1")
199  mStartPattern = Switch1;
200  else if (pattern == "switch2")
201  mStartPattern = Switch2;
202  else if (pattern == "tribute")
203  mStartPattern = Tribute;
204  else
205  std::cout << "Available patterns are: gun, acorn, switch1, switch2\n";
206  }
207  }
208 
209  void build();
210 
211 };
std::string_view data
A string encoding the initial pattern.
Definition: ConwayLife.h:43
Exit the application.
Definition: ConwayLife.h:151
PatternOrigin origin
The general origin of the pattern.
Definition: ConwayLife.h:37
State
The state of a cell.
Definition: ConwayLife.h:80
Cell is empty.
Definition: ConwayLife.h:81
uint32_t SignalToken
A type definition for SignalToken used to identify the source of a Signal.
Definition: Types.h:53
Cell is dead on the next generation.
Definition: ConwayLife.h:83
Definition: ConwayLife.h:36
The value that can be used for the first SignalToken of a user application.
Definition: Constants.h:61
Centered on the board.
Definition: ConwayLife.h:33
Definition: ConwayLife.h:159
Definition: ConwayLife.h:94
rose::Size boardSize
The size of the board in cells.
Definition: ConwayLife.h:39
A position in integer (x, y) co-ordinates.
Definition: Types.h:95
Constants and Enumerations.
Bottom left corner of the board.
Definition: ConwayLife.h:32
Cell is alive on the next generation.
Definition: ConwayLife.h:84
Cell is living.
Definition: ConwayLife.h:82
Restart with the Switch1 pattern.
Definition: ConwayLife.h:154
size_t pixelSize
The size of the square pixels that represent cells.
Definition: ConwayLife.h:38
rose::Position delay
The delay in generations before automatic scrolling.
Definition: ConwayLife.h:41
PatternOrigin
Set the general location of the pattern initialization.
Definition: ConwayLife.h:30
Top left corner of the board.
Definition: ConwayLife.h:31
UserSignalTokenValues
Signal tokens used to identify which button was pressed.
Definition: ConwayLife.h:150
Definition: ConwayLife.h:87
A composite of a Position and a Size.
Definition: Types.h:307
rose::Position offset
The off set from origin to place the initial pattern in. Corrects for pattern size.
Definition: ConwayLife.h:40
Conway&#39;s Tribute pattern.
Definition: ConwayLife.h:156
An element of the application user interface.
Definition: Visual.h:451
Written as a workaround for an issue in the SDL2 Library.
Definition: Renderer.h:64
A size in integer dimensions.
Definition: Types.h:230
Restart with the Gosner Glider Gun pattern.
Definition: ConwayLife.h:152
rose::Position velocity
The velocity and direction of automatic scrolling in generations per cell.
Definition: ConwayLife.h:42
Restart with the Switch2 pattern.
Definition: ConwayLife.h:155
Establish an intra-application signaling protocol.
Restart with the Acorn pattern.
Definition: ConwayLife.h:153