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

Last change on this file since 1403 was 1403, 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}
167
168// ------------------------------------------------------------------------
169//
170// Destructor. Deletes TClonesArrays for hexagons and legend elements.
171//
172MineSweeper::~MineSweeper()
173{
174 Free();
175
176 delete fShow;
177
178 if (fDone)
179 delete fDone;
180
181 // if (fIsAllocated)
182 // delete fDrawingPad;
183}
184
185// ------------------------------------------------------------------------
186//
187// This is called at any time the canvas should get repainted.
188// Here we maintain an aspect ratio of 5/4=1.15. This makes sure,
189// that the camera image doesn't get distorted by resizing the canvas.
190//
191void MineSweeper::Paint(Option_t *opt)
192{
193 const UInt_t w = (UInt_t)(gPad->GetWw()*gPad->GetAbsWNDC());
194 const UInt_t h = (UInt_t)(gPad->GetWh()*gPad->GetAbsHNDC());
195
196 //
197 // Check for a change in width or height, and make sure, that the
198 // first call also sets the range
199 //
200 if (w*fH == h*fW && fW && fH)
201 return;
202
203 //
204 // Calculate aspect ratio (5/4=1.25 recommended)
205 //
206 const Double_t ratio = (Double_t)w/h;
207
208 Float_t x;
209 Float_t y;
210
211 if (ratio>1.0)
212 {
213 x = fRange*(ratio*2-1);
214 y = fRange;
215 }
216 else
217 {
218 x = fRange;
219 y = fRange/ratio;
220 }
221
222 fH = h;
223 fW = w;
224
225 //
226 // Set new range
227 //
228 fDrawingPad->Range(-fRange, -y, x, y);
229
230 //
231 // Adopt absolute sized of markers to relative range
232 //
233 for (UInt_t i=0; i<fNumPixels; i++)
234 {
235 Float_t r = (*this)[i].GetD()*gPad->XtoAbsPixel(1)/325;
236 GetFlag(i)->SetMarkerSize(20.0*r/fRange);
237 }
238}
239
240// ------------------------------------------------------------------------
241//
242// Call this function to draw the camera layout into your canvas.
243// Setup a drawing canvas. Add this object and all child objects
244// (hexagons, etc) to the current pad. If no pad exists a new one is
245// created.
246//
247void MineSweeper::Draw(Option_t *option)
248{
249 // root 3.02:
250 // gPad->SetFixedAspectRatio()
251
252 if (fDrawingPad)
253 return;
254
255 //
256 // if no canvas is yet existing to draw into, create a new one
257 //
258 if (!gPad)
259 {
260 /*TCanvas *c =*/ new TCanvas("MineSweeper", "Magic Mine Sweeper", 0, 0, 800, 800);
261 //c->ToggleEventStatus();
262 fIsAllocated = kTRUE;
263 }
264 else
265 fIsAllocated = kFALSE;
266
267 fDrawingPad = gPad;
268 fDrawingPad->SetBorderMode(0);
269
270 //
271 // Append this object, so that the aspect ratio is maintained
272 // (Paint-function is called)
273 //
274 AppendPad(option);
275
276 //
277 // Reset the game pad
278 //
279 Reset();
280 DrawHexagons();
281}
282
283void MineSweeper::Update(Int_t num)
284{
285 TString txt = "Pixels: ";
286 txt += fNumPixels;
287 txt += " Bombs: ";
288 txt += num;
289
290 fShow->SetText(0, fRange, txt);
291}
292
293// ------------------------------------------------------------------------
294//
295// reset the all pixel colors to a default value
296//
297void MineSweeper::Reset()
298{
299 if (!fShow)
300 {
301
302 fShow = new TText;
303 fShow->SetTextAlign(23); // centered/bottom
304#if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06)
305 fShow->SetBit(kNoContextMenu|kCannotPick);
306#endif
307 fShow->Draw();
308 }
309
310 if (fDone)
311 {
312 delete fDone;
313 fDone = NULL;
314 }
315
316 for (UInt_t i=0; i<fNumPixels; i++)
317 {
318 Remove(GetText(i));
319 Remove(GetFlag(i));
320
321 (*this)[i].SetFillColor(kHidden);
322 (*fGeomCam)[i].ResetBit(kHasBomb|kIsVisible|kHasFlag);
323
324 GetFlag(i)->SetMarkerColor(kBlack);
325 }
326 Update(fNumBombs);
327
328 for (int i=0; i<fNumBombs; i++)
329 {
330 Int_t idx;
331
332 TRandom rnd(0);
333 while (1)
334 {
335 idx = (Int_t)rnd.Uniform(fNumPixels);
336 if (!(*fGeomCam)[idx].TestBit(kHasBomb))
337 break;
338 }
339
340 (*fGeomCam)[idx].SetBit(kHasBomb);
341 }
342
343 fDrawingPad->SetFillColor(22);
344
345#if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06)
346 fDrawingPad->SetBit(kNoContextMenu);
347 SetBit(kNoContextMenu);
348#endif
349}
350
351void MineSweeper::Done(TString txt, Int_t col)
352{
353 for (unsigned int j=0; j<fNumPixels; j++)
354 if ((*fGeomCam)[j].TestBit(kHasBomb))
355 {
356 (*this)[j].SetFillColor(kBlack);
357 GetFlag(j)->SetMarkerColor(kWhite);
358 }
359
360 fDone = new TText(0, 0, txt);
361 fDone->SetTextColor(kWhite); // white
362 fDone->SetTextAlign(22); // centered/centered
363 fDone->SetTextSize(0.05); // white
364#if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06)
365 fDone->SetBit(kNoContextMenu|kCannotPick);
366#endif
367 fDone->Draw();
368
369 fDrawingPad->SetFillColor(col);
370
371#if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06)
372 fDrawingPad->ResetBit(kNoContextMenu);
373 ResetBit(kNoContextMenu);
374#endif
375}
376
377// ------------------------------------------------------------------------
378//
379// Check whether a hexagon should be opened and which color/number should
380// be visible
381//
382void MineSweeper::OpenHexagon(Int_t idx)
383{
384 MGeomPix &pix=(*fGeomCam)[idx];
385
386 if (pix.TestBit(kIsVisible))
387 return;
388
389 if (pix.TestBit(kHasFlag))
390 Remove(GetFlag(idx));
391
392 pix.SetBit(kIsVisible);
393 pix.ResetBit(kHasFlag);
394
395 Int_t cnt=0;
396 for (int j=0; j<pix.GetNumNeighbors(); j++)
397 if ((*fGeomCam)[pix.GetNeighbor(j)].TestBit(kHasBomb))
398 cnt++;
399
400 (*this)[idx].SetFillColor(fColorBombs[cnt]);
401
402 if (cnt)
403 {
404 TText *txt = GetText(idx);
405 TString str;
406 str += cnt;
407 txt->SetText(pix.GetX(), pix.GetY(), str);
408 txt->Draw();
409 return;
410 }
411
412 for (int j=0; j<pix.GetNumNeighbors(); j++)
413 OpenHexagon(pix.GetNeighbor(j));
414}
415
416void MineSweeper::Remove(TObject *obj)
417{
418 fDrawingPad->RecursiveRemove(obj);
419}
420
421// ------------------------------------------------------------------------
422//
423// Execute a mouse event on the camera
424//
425void MineSweeper::ExecuteEvent(Int_t event, Int_t px, Int_t py)
426{
427 if (event==kMouseMotion || event==kMouseEnter || event==kMouseLeave ||
428 event==kButton1Up || event==kButton2Up || event==kButton3Up ||
429 event==kButton1Motion || event==kButton2Motion || event==kButton3Motion ||
430 event==kButton2Double || event==kButton3Double ||
431 fDone)
432 return;
433
434 //cout << "Execute Event Camera " << event << " @ " << px << " " << py << endl;
435
436 UInt_t idx;
437 for (idx=0; idx<fNumPixels; idx++)
438 if ((*fPixels)[idx]->DistancetoPrimitive(px, py)==0)
439 break;
440
441 if (idx==fNumPixels)
442 return;
443
444 MGeomPix &pix=(*fGeomCam)[idx];
445
446 if (event==kButton1Double)
447 {
448 OpenHexagon(idx);
449
450 if (pix.TestBit(kHasBomb))
451 Done("Argh... you hit the Bomb!!!", 2);
452 }
453
454 if (event==kButton1Down && !pix.TestBit(kIsVisible))
455 {
456 if (pix.TestBit(kHasFlag))
457 Remove(GetFlag(idx));
458 else
459 GetFlag(idx)->Draw();
460
461 pix.InvertBit(kHasFlag);
462 }
463
464 UInt_t vis=fNumBombs;
465 UInt_t flg=fNumBombs;
466 for (UInt_t i=0; i<fNumPixels; i++)
467 {
468 if ((*fGeomCam)[i].TestBit(kIsVisible))
469 vis++;
470 if ((*fGeomCam)[i].TestBit(kHasFlag))
471 flg--;
472 }
473
474 Update(flg);
475
476 if (vis==fNumPixels)
477 Done("Great! Congratulations, you did it!", 3);
478
479 fDrawingPad->Modified();
480
481 /*
482 switch (event)
483 {
484 case kNoEvent: cout << "No Event" << endl; break;
485 case kButton1Down: cout << "Button 1 down" << endl; break;
486 case kButton2Down: cout << "Button 2 down" << endl; break;
487 case kButton3Down: cout << "Button 3 down" << endl; break;
488 case kKeyDown: cout << "Key down" << endl; break;
489 case kKeyUp: cout << "Key up" << endl; break;
490 case kKeyPress: cout << "Key press" << endl; break;
491 case kButton1Locate: cout << "Button 1 locate" << endl; break;
492 case kButton2Locate: cout << "Button 2 locate" << endl; break;
493 case kButton3Locate: cout << "Button 3 locate" << endl; break;
494 }
495 */
496}
Note: See TracBrowser for help on using the repository browser.