add non-functional c1 Hatchery
[openc2e.git] / tools / braininavat / braininavat.cpp
blob532bdf79ecbcbac9cea22e0468da6337007fd2dd
1 /*
2 This program is free software; you can redistribute it and/or modify
3 it under the terms of the GNU General Public License as published by
4 the Free Software Foundation; either version 2 of the License, or
5 (at your option) any later version.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
12 You should have received a copy of the GNU General Public License along
13 with this program; if not, write to the Free Software Foundation, Inc.,
14 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 #include "braininavat.h"
18 #include <QtGui>
19 #include "brainview.h"
20 #include "c2eBrain.h"
22 #include <fstream>
23 using namespace std;
25 // Constructor which creates the main window.
27 BrainInAVat::BrainInAVat() {
28 ourCreature = 0;
29 scrollArea = new QScrollArea(this);
30 ourView = new BrainView();
31 scrollArea->setWidget(ourView);
32 setCentralWidget(scrollArea);
34 (void)statusBar();
35 setWindowTitle(tr("openc2e's Brain in a Vat"));
36 resize(600, 400);
38 /* File menu */
40 openAct = new QAction(tr("&Open..."), this);
41 openAct->setShortcut(tr("Ctrl+O"));
42 openAct->setStatusTip(tr("Open a genome file"));
43 connect(openAct, SIGNAL(triggered()), this, SLOT(open()));
45 for (int i = 0; i < MaxRecentFiles; ++i) {
46 recentFileActs[i] = new QAction(this);
47 recentFileActs[i]->setVisible(false);
48 connect(recentFileActs[i], SIGNAL(triggered()), this, SLOT(openRecentFile()));
51 exitAct = new QAction(tr("E&xit"), this);
52 exitAct->setShortcut(tr("Ctrl+Q"));
53 exitAct->setStatusTip(tr("Exit Brain in a Vat"));
54 connect(exitAct, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()));
56 fileMenu = menuBar()->addMenu(tr("&File"));
57 fileMenu->addAction(openAct);
58 separatorAct = fileMenu->addSeparator();
59 for (int i = 0; i < MaxRecentFiles; ++i)
60 fileMenu->addAction(recentFileActs[i]);
61 fileMenu->addSeparator();
62 fileMenu->addAction(exitAct);
63 updateRecentFileActions();
65 /* View menu */
67 neuronActGroup = new QActionGroup(this);
68 dendriteActGroup = new QActionGroup(this);
69 thresholdActGroup = new QActionGroup(this);
71 // neuron/dendrite variable selection
72 for (unsigned int i = 0; i < 8; i++) {
73 // TODO: friendly names for neuron/dendrite vars
75 neuronActs[i] = new QAction(tr("Neuron var %1").arg(i), this);
76 neuronActGroup->addAction(neuronActs[i]);
77 neuronActs[i]->setCheckable(true);
78 connect(neuronActs[i], SIGNAL(triggered()), this, SLOT(setSomeVar()));
79 dendriteActs[i] = new QAction(tr("Dendrite var %1").arg(i), this);
80 dendriteActGroup->addAction(dendriteActs[i]);
81 dendriteActs[i]->setCheckable(true);
82 connect(dendriteActs[i], SIGNAL(triggered()), this, SLOT(setSomeVar()));
84 neuronActs[0]->setChecked(true);
85 dendriteActs[0]->setChecked(true);
87 // threshold for element visibility
88 noThresholdAct = new QAction(tr("Show all elements"), this);
89 thresholdActGroup->addAction(noThresholdAct);
90 noThresholdAct->setCheckable(true);
91 noThresholdAct->setChecked(true);
92 connect(noThresholdAct, SIGNAL(triggered()), this, SLOT(setNoThreshold()));
93 nonZeroThresholdAct = new QAction(tr("Show elements with non-zero values only"), this);
94 thresholdActGroup->addAction(nonZeroThresholdAct);
95 nonZeroThresholdAct->setCheckable(true);
96 connect(nonZeroThresholdAct, SIGNAL(triggered()), this, SLOT(setNonZeroThreshold()));
97 showNoneAct = new QAction(tr("Show no elements"), this);
98 thresholdActGroup->addAction(showNoneAct);
99 showNoneAct->setCheckable(true);
100 connect(showNoneAct, SIGNAL(triggered()), this, SLOT(setShowNone()));
102 viewMenu = menuBar()->addMenu(tr("&View"));
103 for (unsigned int i = 0; i < 8; i++)
104 viewMenu->addAction(neuronActs[i]);
105 viewMenu->addSeparator();
106 for (unsigned int i = 0; i < 8; i++)
107 viewMenu->addAction(dendriteActs[i]);
108 viewMenu->addSeparator();
109 viewMenu->addAction(noThresholdAct);
110 viewMenu->addAction(nonZeroThresholdAct);
111 viewMenu->addAction(showNoneAct);
113 /* Control menu */
115 tickAct = new QAction(tr("&Tick"), this);
116 tickAct->setStatusTip(tr("Run the brain through one iteration"));
117 tickAct->setEnabled(false);
118 connect(tickAct, SIGNAL(triggered()), this, SLOT(tick()));
120 sleepToggleAct = new QAction(tr("&Sleep"), this);
121 sleepToggleAct->setStatusTip(tr("Set whether the brain is asleep (and dreaming) or not"));
122 sleepToggleAct->setCheckable(true);
123 sleepToggleAct->setEnabled(false);
124 connect(sleepToggleAct, SIGNAL(triggered()), this, SLOT(toggleSleep()));
126 controlMenu = menuBar()->addMenu(tr("&Control"));
127 controlMenu->addAction(tickAct);
128 controlMenu->addAction(sleepToggleAct);
130 controlToolbar = addToolBar(tr("Control"));
131 controlToolbar->addAction(tickAct);
133 /* Help menu */
135 menuBar()->addSeparator();
137 aboutAct = new QAction(tr("&About"), this);
138 aboutAct->setStatusTip(tr("Find out about Brain in a Vat"));
139 connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
141 helpMenu = menuBar()->addMenu(tr("&Help"));
142 helpMenu->addAction(aboutAct);
145 BrainInAVat::~BrainInAVat() {
146 if (ourCreature)
147 delete ourCreature;
148 delete ourView;
151 // action handlers
153 void BrainInAVat::open() {
154 QString fileName = QFileDialog::getOpenFileName(this, tr("Pick a genome"), QString(), tr("Genomes (*.gen)"));
155 if (!fileName.isEmpty())
156 loadFile(fileName);
159 void BrainInAVat::openRecentFile() {
160 QAction *action = qobject_cast<QAction *>(sender());
162 if (action)
163 loadFile(action->data().toString());
166 void BrainInAVat::about() {
167 QMessageBox::about(this, tr("openc2e's Brain in a Vat"), tr("An openc2e tool to monitor and experiment upon creature brains."));
170 void BrainInAVat::tick() {
171 // brain updates are every 4 ticks
172 // TODO: this is icky
173 for (unsigned int i = 0; i < 4; i++)
174 ourCreature->tick();
176 ourView->update();
179 void BrainInAVat::setSomeVar() {
180 QAction *action = qobject_cast<QAction *>(sender());
182 for (unsigned int i = 0; i < 8; i++) {
183 if (action == neuronActs[i])
184 ourView->neuron_var = i;
185 else if (action == dendriteActs[i])
186 ourView->dendrite_var = i;
189 ourView->update();
192 void BrainInAVat::setNoThreshold() {
193 ourView->threshold = -1000.0f;
194 ourView->update();
197 void BrainInAVat::setNonZeroThreshold() {
198 ourView->threshold = 0.0f;
199 ourView->update();
202 void BrainInAVat::setShowNone() {
203 ourView->threshold = 1000.0f;
204 ourView->update();
207 void BrainInAVat::toggleSleep() {
208 ourCreature->setDreaming(!ourCreature->isDreaming());
209 sleepToggleAct->setChecked(ourCreature->isDreaming());
212 // code to Do Things!
214 void BrainInAVat::loadFile(const QString &fileName) {
215 // zot any existing file
216 setCurrentFile(QString());
217 if (ourCreature) {
218 delete ourCreature;
219 ourCreature = 0;
220 ourView->setCreature(ourCreature);
222 tickAct->setEnabled(false);
223 sleepToggleAct->setChecked(false);
224 sleepToggleAct->setEnabled(false);
225 ourView->update();
227 ifstream f(fileName.toAscii(), std::ios::binary);
228 if (f.fail()) {
229 QMessageBox::warning(this, tr("openc2e's Brain in a Vat"), tr("Cannot read file %1.").arg(fileName));
230 return;
233 QApplication::setOverrideCursor(Qt::WaitCursor);
235 // read genome
236 f >> noskipws;
237 shared_ptr<genomeFile> gfile(new genomeFile());
238 try {
239 f >> *gfile;
240 } catch (genomeException &e) {
241 QApplication::restoreOverrideCursor();
242 QMessageBox::warning(this, tr("openc2e's Brain in a Vat"), tr("Failed loading the genome due to error '%1'!").arg(e.what()));
243 return;
246 // TODO: dialog to pick age, gender, variant?
248 // create creature
249 if (gfile->getVersion() == 3) {
250 try {
251 ourCreature = new c2eCreature(gfile, true, 0);
252 } catch (creaturesException &e) {
253 QApplication::restoreOverrideCursor();
254 QMessageBox::warning(this, tr("openc2e's Brain in a Vat"), e.what());
255 return;
257 } else {
258 QApplication::restoreOverrideCursor();
259 QMessageBox::warning(this, tr("openc2e's Brain in a Vat"), tr("This genome is of version %1, which is unsupported.").arg(gfile->getVersion()));
260 return;
263 QApplication::restoreOverrideCursor();
265 ourView->setCreature(ourCreature);
267 // we're done; update title/recent files, and display a temporary status message
268 tickAct->setEnabled(true);
269 sleepToggleAct->setEnabled(true);
270 ourView->resize(ourView->minimumSize());
271 ourView->update();
272 setCurrentFile(fileName);
273 statusBar()->showMessage(tr("Loaded %1 genes").arg(gfile->genes.size()), 2000);
276 // Some Recent Files magic.
278 void BrainInAVat::setCurrentFile(const QString &fileName) {
279 curFile = fileName;
280 if (curFile.isEmpty()) {
281 setWindowTitle(tr("openc2e's Brain in a Vat"));
282 return; // TODO: is this correct?
283 } else
284 setWindowTitle(tr("%1 - %2").arg(strippedName(curFile)).arg(tr("openc2e's Brain in a Vat")));
286 // read the list of recent files
287 QSettings settings("ccdevnet.org", "Brain In A Vat");
288 QStringList files = settings.value("recentFileList").toStringList();
290 // make sure the current file is at the top!
291 files.removeAll(fileName);
292 files.prepend(fileName);
293 // remove any which are over the size
294 while (files.size() > MaxRecentFiles)
295 files.removeLast();
297 // store the list of recent files
298 settings.setValue("recentFileList", files);
300 // update ourselves..
301 updateRecentFileActions(); // obviously assumes we only have one window
304 void BrainInAVat::updateRecentFileActions() {
305 // read the list of recent files
306 QSettings settings("ccdevnet.org", "Brain In A Vat");
307 QStringList files = settings.value("recentFileList").toStringList();
309 // enable recent files actions as needed
310 int numRecentFiles = qMin(files.size(), (int)MaxRecentFiles);
311 for (int i = 0; i < numRecentFiles; ++i) {
312 QString text = tr("&%1 %2").arg(i + 1).arg(strippedName(files[i]));
313 recentFileActs[i]->setText(text);
314 recentFileActs[i]->setData(files[i]);
315 recentFileActs[i]->setVisible(true);
318 // make sure the rest are disabled [ie, hidden]
319 for (int j = numRecentFiles; j < MaxRecentFiles; ++j)
320 recentFileActs[j]->setVisible(false);
322 // only show the separator if there are recent files
323 separatorAct->setVisible(numRecentFiles > 0);
326 QString BrainInAVat::strippedName(const QString &fullFileName) {
327 return QFileInfo(fullFileName).fileName();