source: trunk/MagicSoft/Mars/mgui/MineSweeper.cc@ 1402

Last change on this file since 1402 was 1402, checked in by tbretz, 22 years ago
*** empty log message ***
File size: 11.8 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of MARS, the MAGIC Analysis and Reconstruction
5! * Software. It is distributed to you in the hope that it can be a useful
6! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
7! * It is distributed WITHOUT ANY WARRANTY.
8! *
9! * Permission to use, copy, modify and distribute this software and its
10! * documentation for any purpose is hereby granted without fee,
11! * provided that the above copyright notice appear in all copies and
12! * that both that copyright notice and this permission notice appear
13! * in supporting documentation. It is provided "as is" without express
14! * or implied warranty.
15! *
16!
17!
18! Author(s): Thomas Bretz 07/2002 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2002
21!
22!
23\* ======================================================================== */
24
25/////////////////////////////////////////////////////////////////////////////
26//
27// MineSweeper
28//
29// Camera Display Games
30//
31////////////////////////////////////////////////////////////////////////////
32#include "MineSweeper.h"
33
34#include <math.h>
35#include <fstream.h>
36#include <iostream.h>
37
38#include <TClonesArray.h>
39#include <TCanvas.h>
40#include <TText.h>
41#include <TMarker.h>
42#include <TRandom.h>
43
44#include "MHexagon.h"
45
46#include "MGeomPix.h"
47#include "MGeomCamCT1.h"
48#include "MGeomCamMagic.h"
49
50ClassImp(MineSweeper);
51
52// gelb grn blau trkis rosa rot
53// 0, 1 2 3 4 5 6
54static Int_t InitColors[7] = { 22, 5, 3, 4, 7, 6, 2 };
55
56void MineSweeper::Free()
57{
58 if (!fGeomCam)
59 return;
60
61 fPixels->Delete();
62 fText->Delete();
63 fFlags->Delete();
64
65 delete fText;
66 delete fFlags;
67 delete fPixels;
68
69 delete fGeomCam;
70}
71
72void MineSweeper::ChangeCamera()
73{
74 static Bool_t ct1=kFALSE;
75
76 cout << "Change to " << (ct1?"Magic":"CT1") << endl;
77
78 if (ct1)
79 SetNewCamera(new MGeomCamMagic);
80 else
81 SetNewCamera(new MGeomCamCT1);
82
83 ct1 = !ct1;
84
85 Reset();
86 DrawHexagons();
87}
88
89void MineSweeper::SetNewCamera(MGeomCam *geom)
90{
91 Free();
92
93 //
94 // Reset the display geometry
95 //
96 fW=0;
97 fH=0;
98
99 //
100 // Set new camera
101 //
102 fGeomCam = geom;
103
104 //
105 // create the hexagons of the display
106 //
107 fNumPixels = fGeomCam->GetNumPixels();
108 fRange = fGeomCam->GetMaxRadius();
109
110 //
111 // Construct all hexagons. Use new-operator with placement
112 //
113 fNumBombs = fNumPixels/5;
114
115 fText = new TClonesArray("TText", fNumPixels);
116 fFlags = new TClonesArray("TMarker", fNumPixels);
117 fPixels = new TClonesArray("MHexagon", fNumPixels);
118
119 for (UInt_t i=0; i<fNumPixels; i++)
120 {
121 MHexagon &h = *new ((*fPixels)[i]) MHexagon((*fGeomCam)[i]);
122#if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06)
123 h.SetBit(kNoContextMenu|kCannotPick);
124#endif
125
126 TText &t = *new ((*fText)[i]) TText;
127 t.SetTextFont(122);
128 t.SetTextAlign(22); // centered/centered
129 t.SetTextSize(0.3*h.GetD()/fRange);
130#if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06)
131 t.SetBit(kNoContextMenu|kCannotPick);
132#endif
133
134 const MGeomPix &pix = (*fGeomCam)[i];
135
136 TMarker &m = *new ((*fFlags)[i]) TMarker(pix.GetX(), pix.GetY(), kOpenStar);
137#if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06)
138 m.SetBit(kNoContextMenu|kCannotPick);
139#endif
140 }
141}
142
143// ------------------------------------------------------------------------
144//
145// Draw all pixels of the camera
146// (means apend all pixelobjects to the current pad)
147//
148void MineSweeper::DrawHexagons()
149{
150 for (UInt_t i=0; i<fNumPixels; i++)
151 (*this)[i].Draw();
152}
153
154// ------------------------------------------------------------------------
155//
156// default constructor
157//
158MineSweeper::MineSweeper()
159 : fGeomCam(NULL), fDone(NULL), fShow(NULL), fW(0), fH(0), fDrawingPad(NULL), fIsAllocated(kFALSE)
160{
161 memcpy(fColorBombs, InitColors, sizeof(InitColors));
162
163 SetNewCamera(new MGeomCamMagic);
164
165 Draw();
166 SetBit(kCanDelete);
167}
168
169// ------------------------------------------------------------------------
170//
171// Destructor. Deletes TClonesArrays for hexagons and legend elements.
172//
173MineSweeper::~MineSweeper()
174{
175 Free();
176
177 delete fShow;
178
179 if (fDone)
180 delete fDone;
181
182 if (fIsAllocated)
183 delete fDrawingPad;
184}
185
186// ------------------------------------------------------------------------
187//
188// This is called at any time the canvas should get repainted.
189// Here we maintain an aspect ratio of 5/4=1.15. This makes sure,
190// that the camera image doesn't get distorted by resizing the canvas.
191//
192void MineSweeper::Paint(Option_t *opt)
193{
194 const UInt_t w = (UInt_t)(gPad->GetWw()*gPad->GetAbsWNDC());
195 const UInt_t h = (UInt_t)(gPad->GetWh()*gPad->GetAbsHNDC());
196
197 //
198 // Check for a change in width or height, and make sure, that the
199 // first call also sets the range
200 //
201 if (w*fH == h*fW && fW && fH)
202 return;
203
204 //
205 // Calculate aspect ratio (5/4=1.25 recommended)
206 //
207 const Double_t ratio = (Double_t)w/h;
208
209 Float_t x;
210 Float_t y;
211
212 if (ratio>1.0)
213 {
214 x = fRange*(ratio*2-1);
215 y = fRange;
216 }
217 else
218 {
219 x = fRange;
220 y = fRange/ratio;
221 }
222
223 fH = h;
224 fW = w;
225
226 //
227 // Set new range
228 //
229 fDrawingPad->Range(-fRange, -y, x, y);
230
231 //
232 // Adopt absolute sized of markers to relative range
233 //
234 for (UInt_t i=0; i<fNumPixels; i++)
235 {
236 Float_t r = (*this)[i].GetD()*gPad->XtoAbsPixel(1)/325;
237 GetFlag(i)->SetMarkerSize(20.0*r/fRange);
238 }
239}
240
241// ------------------------------------------------------------------------
242//
243// Call this function to draw the camera layout into your canvas.
244// Setup a drawing canvas. Add this object and all child objects
245// (hexagons, etc) to the current pad. If no pad exists a new one is
246// created.
247//
248void MineSweeper::Draw(Option_t *option)
249{
250 // root 3.02:
251 // gPad->SetFixedAspectRatio()
252
253 if (fDrawingPad)
254 return;
255
256 //
257 // if no canvas is yet existing to draw into, create a new one
258 //
259 if (!gPad)
260 {
261 /*TCanvas *c =*/ new TCanvas("MineSweeper", "Magic Mine Sweeper", 0, 0, 800, 800);
262 //c->ToggleEventStatus();
263 fIsAllocated = kTRUE;
264 }
265 else
266 fIsAllocated = kFALSE;
267
268 fDrawingPad = gPad;
269 fDrawingPad->SetBorderMode(0);
270
271 //
272 // Append this object, so that the aspect ratio is maintained
273 // (Paint-function is called)
274 //
275 AppendPad(option);
276
277 //
278 // Reset the game pad
279 //
280 Reset();
281 DrawHexagons();
282}
283
284void MineSweeper::Update(Int_t num)
285{
286 TString txt = "Pixels: ";
287 txt += fNumPixels;
288 txt += " Bombs: ";
289 txt += num;
290
291 fShow->SetText(0, fRange, txt);
292}
293
294// ------------------------------------------------------------------------
295//
296// reset the all pixel colors to a default value
297//
298void MineSweeper::Reset()
299{
300 if (!fShow)
301 {
302
303 fShow = new TText;
304 fShow->SetTextAlign(23); // centered/bottom
305#if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06)
306 fShow->SetBit(kNoContextMenu|kCannotPick);
307#endif
308 fShow->Draw();
309 }
310
311 if (fDone)
312 {
313 delete fDone;
314 fDone = NULL;
315 }
316
317 for (UInt_t i=0; i<fNumPixels; i++)
318 {
319 Remove(GetText(i));
320 Remove(GetFlag(i));
321
322 (*this)[i].SetFillColor(kHidden);
323 (*fGeomCam)[i].ResetBit(kHasBomb|kIsVisible|kHasFlag);
324
325 GetFlag(i)->SetMarkerColor(kBlack);
326 }
327 Update(fNumBombs);
328
329 for (int i=0; i<fNumBombs; i++)
330 {
331 Int_t idx;
332
333 TRandom rnd(0);
334 while (1)
335 {
336 idx = (Int_t)rnd.Uniform(fNumPixels);
337 if (!(*fGeomCam)[idx].TestBit(kHasBomb))
338 break;
339 }
340
341 (*fGeomCam)[idx].SetBit(kHasBomb);
342 }
343
344 fDrawingPad->SetFillColor(22);
345
346#if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06)
347 fDrawingPad->SetBit(kNoContextMenu);
348 SetBit(kNoContextMenu);
349#endif
350}
351
352void MineSweeper::Done(TString txt, Int_t col)
353{
354 for (unsigned int j=0; j<fNumPixels; j++)
355 if ((*fGeomCam)[j].TestBit(kHasBomb))
356 {
357 (*this)[j].SetFillColor(kBlack);
358 GetFlag(j)->SetMarkerColor(kWhite);
359 }
360
361 fDone = new TText(0, 0, txt);
362 fDone->SetTextColor(kWhite); // white
363 fDone->SetTextAlign(22); // centered/centered
364 fDone->SetTextSize(0.05); // white
365#if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06)
366 fDone->SetBit(kNoContextMenu|kCannotPick);
367#endif
368 fDone->Draw();
369
370 fDrawingPad->SetFillColor(col);
371
372#if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06)
373 fDrawingPad->ResetBit(kNoContextMenu);
374 ResetBit(kNoContextMenu);
375#endif
376}
377
378// ------------------------------------------------------------------------
379//
380// Check whether a hexagon should be opened and which color/number should
381// be visible
382//
383void MineSweeper::OpenHexagon(Int_t idx)
384{
385 MGeomPix &pix=(*fGeomCam)[idx];
386
387 if (pix.TestBit(kIsVisible))
388 return;
389
390 if (pix.TestBit(kHasFlag))
391 Remove(GetFlag(idx));
392
393 pix.SetBit(kIsVisible);
394 pix.ResetBit(kHasFlag);
395
396 Int_t cnt=0;
397 for (int j=0; j<pix.GetNumNeighbors(); j++)
398 if ((*fGeomCam)[pix.GetNeighbor(j)].TestBit(kHasBomb))
399 cnt++;
400
401 (*this)[idx].SetFillColor(fColorBombs[cnt]);
402
403 if (cnt)
404 {
405 TText *txt = GetText(idx);
406 TString str;
407 str += cnt;
408 txt->SetText(pix.GetX(), pix.GetY(), str);
409 txt->Draw();
410 return;
411 }
412
413 for (int j=0; j<pix.GetNumNeighbors(); j++)
414 OpenHexagon(pix.GetNeighbor(j));
415}
416
417void MineSweeper::Remove(TObject *obj)
418{
419 fDrawingPad->RecursiveRemove(obj);
420}
421
422// ------------------------------------------------------------------------
423//
424// Execute a mouse event on the camera
425//
426void MineSweeper::ExecuteEvent(Int_t event, Int_t px, Int_t py)
427{
428 if (event==kMouseMotion || event==kMouseEnter || event==kMouseLeave ||
429 event==kButton1Up || event==kButton2Up || event==kButton3Up ||
430 event==kButton1Motion || event==kButton2Motion || event==kButton3Motion ||
431 event==kButton2Double || event==kButton3Double ||
432 fDone)
433 return;
434
435 //cout << "Execute Event Camera " << event << " @ " << px << " " << py << endl;
436
437 UInt_t idx;
438 for (idx=0; idx<fNumPixels; idx++)
439 if ((*fPixels)[idx]->DistancetoPrimitive(px, py)==0)
440 break;
441
442 if (idx==fNumPixels)
443 return;
444
445 MGeomPix &pix=(*fGeomCam)[idx];
446
447 if (event==kButton1Double)
448 {
449 OpenHexagon(idx);
450
451 if (pix.TestBit(kHasBomb))
452 Done("Argh... you hit the Bomb!!!", 2);
453 }
454
455 if (event==kButton1Down && !pix.TestBit(kIsVisible))
456 {
457 if (pix.TestBit(kHasFlag))
458 Remove(GetFlag(idx));
459 else
460 GetFlag(idx)->Draw();
461
462 pix.InvertBit(kHasFlag);
463 }
464
465 UInt_t vis=fNumBombs;
466 UInt_t flg=fNumBombs;
467 for (UInt_t i=0; i<fNumPixels; i++)
468 {
469 if ((*fGeomCam)[i].TestBit(kIsVisible))
470 vis++;
471 if ((*fGeomCam)[i].TestBit(kHasFlag))
472 flg--;
473 }
474
475 Update(flg);
476
477 if (vis==fNumPixels)
478 Done("Great! Congratulations, you did it!", 3);
479
480 fDrawingPad->Modified();
481
482 /*
483 switch (event)
484 {
485 case kNoEvent: cout << "No Event" << endl; break;
486 case kButton1Down: cout << "Button 1 down" << endl; break;
487 case kButton2Down: cout << "Button 2 down" << endl; break;
488 case kButton3Down: cout << "Button 3 down" << endl; break;
489 case kKeyDown: cout << "Key down" << endl; break;
490 case kKeyUp: cout << "Key up" << endl; break;
491 case kKeyPress: cout << "Key press" << endl; break;
492 case kButton1Locate: cout << "Button 1 locate" << endl; break;
493 case kButton2Locate: cout << "Button 2 locate" << endl; break;
494 case kButton3Locate: cout << "Button 3 locate" << endl; break;
495 }
496 */
497}
Note: See TracBrowser for help on using the repository browser.