summaryrefslogtreecommitdiff
path: root/Source/Applications/Demos/GOL.cpp
blob: ba9cb1c944244a4940956831efdd2f0abee45c42 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include <Binding/Thread.class.h>
#include <ByteArray.class.h>
#include <Rand.ns.h>

#include <App/ShellApp.proto.h>

class GOL : public ShellApp {
	public:
	GOL() : ShellApp("GOL.app", "Melon's Game of Life simulator \\o/") {}
	int run();
};

APP(GOL);

int GOL::run() {
	if (!outvt.isBoxed()) {
		outvt << "Error : cannot display GOL on a non-boxed terminal.\n";
		return 1;
	}

	int h = outvt.height() - 1, w = outvt.width();

	bool *cells = new bool[w * h];
	bool *newcells = new bool[w * h];

	u32int delay = 100;

	for (u32int x = 0; x < w; x++) {
		for (u32int y = 0; y < h; y++) {
			cells[x * h + y] = false;
		}
	}

	ByteArray tmp((w + 1) * (h + 1));

	bool run = true;
	while (run) {
		//Display cells
		for (u32int y = 0; y < h; y++) {
			for (u32int x = 0; x < w; x++) {
				if (cells[x * h + y]) {
					tmp[y * w + x] = '#';
				} else {
					tmp[y * w + x] = ' ';
				}
			}
		}
		outvt.moveCursor(0, 0);
		outvt.write(tmp.toString());	//BYPASS buffering
		outvt<< "Press Ctrl+h for help" << FLUSH;

		//Compute next generation
		for (int y = 0; y < h; y++) {
			for (int x = 0; x < w; x++) {
				u8int n = 0;
				for (int yy = y - 1; yy < y + 2; yy++) {
					for (int xx = x - 1; xx < x + 2; xx++) {
						if (xx < w and yy < h and xx >= 0 and yy >= 0
							   and cells[xx * h + yy]) n++;
					}
				}
				newcells[x * h + y] = cells[x * h + y];
				if (cells[x * h + y]) {
					n--;
					if (n < 2) newcells[x * h + y] = false;
					if (n > 3) newcells[x * h + y] = false;
				} else {
					if (n == 3) newcells[x*  h + y] = true;
				}

			}
		}
		for (u32int x = 0; x < w; x++) {
			for (u32int y = 0; y < h; y++) {
				cells[x * h + y] = newcells[x * h + y];
			}
		}

		keypress_t kp = invt.getKeypress(false, false);
		while (kp.hascmd && (kp.modifiers & STATUS_CTRL)) {
			if (kp.character == WChar("c")) {
				run = false;
			} else if (kp.character == WChar("r")) {
				for (u32int i = 0; i < 20; i++) {
					u64int x = Rand::rand() * w / Rand::max();
					u64int y = Rand::rand() * h / Rand::max();
					cells[x * h + y] = true;
				}
			} else if (kp.character == WChar("R")) {
				for (u32int i = 0; i < 150; i++) {
					u64int x = Rand::rand() * w / Rand::max();
					u64int y = Rand::rand() * h / Rand::max();
					cells[x * h + y] = true;
				}
			} else if (kp.character == WChar("p")) {
				outvt << " [PAUSED] press a key to resume" << FLUSH;
				invt.getKeypress();
			} else if (kp.character == WChar("h")) {
				outvt << "\n\n** Melon's demo Game Of Life Simulator help :\n";
				outvt << " - ctrl+c : quit\n";
				outvt << " - ctrl+h : show this\n";
				outvt << " - ctrl+p : pause\n";
				outvt << " - ctrl+r : add some random cells\n";
				outvt << " - ctrl+R : add more cells, still random\n\n";
				outvt << "Press any key to return to simultaor..." << FLUSH;
				invt.getKeypress();
			}
			kp = invt.getKeypress(false, false);
		}

		Thread::get().sleep(100);
	}

	delete cells;
	delete newcells;

	outvt << "\n\n";
}