source: trunk/Mars/mtools/MagicJam.cc@ 10498

Last change on this file since 10498 was 9385, checked in by tbretz, 16 years ago
*** empty log message ***
File size: 22.9 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of CheObs, the Modular 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 appears 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, 9/2005 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2005-2008
21!
22!
23\* ======================================================================== */
24
25/////////////////////////////////////////////////////////////////////////////
26//
27// MagicJam
28//
29// Jam is a multi player game. It is controlled by its context menu (click
30// with the right mouse button on one of the pixels in the game pad).
31//
32// Start the game with:
33// MagicJam jam;
34//
35// Rules:
36// MagicJam is a multiplayer game. The aim is to own the full game pad.
37// Ech pixel in the pad can contain as many entries as it has neighbors.
38// If it has more entries than neighbors it overflows into its neighbors.
39// All pixels into which such an overflow occures will be captured by
40// the current player. Player by player will be able to increase the
41// entry in one pixel by one. Increase the contents of an empty pixel to
42// one or by one in an owned pixel. The player who once will own the
43// all pixels will win.
44//
45// Editor:
46// To edit or create a new game start the editor from the context menu
47// of MagicJam. The editor is also controlled from its context menu.
48// Use the curso keys to shift your game.
49// Warning: You MUST create a single-island game. Games which have two
50// islands might result in edless loops. (Currently there is no check!)
51//
52/////////////////////////////////////////////////////////////////////////////
53#include "MagicJam.h"
54
55#include <climits> // INT_MAX (Ubuntu 8.10)
56
57#include <iostream>
58#include <fstream>
59
60#include <errno.h>
61
62#include <KeySymbols.h>
63
64#include <TMath.h>
65#include <TRandom.h>
66
67#include <TBox.h>
68#include <TLine.h>
69#include <TText.h>
70
71#include <TStyle.h>
72#include <TSystem.h>
73
74#include <TNtuple.h>
75#include <TASImage.h>
76#include <TInterpreter.h>
77#include <TGFileDialog.h>
78
79#include "MH.h"
80#include "MHexagon.h"
81#include "MGeomCam.h"
82#include "MGeomPix.h"
83
84#include "MDirIter.h"
85
86ClassImp(MagicJamAbc);
87ClassImp(MagicJamEditor);
88ClassImp(MagicJam);
89
90using namespace std;
91
92// -------------------------------------------------------------------------
93// The editor for MagicJam
94// -------------------------------------------------------------------------
95
96// --------------------------------------------------------------------------
97//
98// Move the contents of the pad
99//
100void MagicJamEditor::Move(int dx, int dy)
101{
102 const TArrayC cpy(fUsed);
103
104 Int_t h = cpy.GetSize()/fWidth;
105
106 for (int i=0; i<cpy.GetSize(); i++)
107 {
108 Int_t x = i%fWidth;
109 Int_t y = i/fWidth;
110
111 x += dx + fWidth;
112 y += dy*2 + h;
113
114 x %= fWidth;
115 y %= h;
116
117 fUsed[x+y*fWidth] = cpy[i];
118 }
119 gPad->GetPad(1)->Modified();
120 gPad->GetPad(1)->Update();
121 gPad->Modified();
122 gPad->Update();
123}
124
125// --------------------------------------------------------------------------
126//
127// Initialize the pad with size wx, hy
128//
129void MagicJamEditor::InitGeom(int wx, int hy)
130{
131 const Float_t dx = 0.5*(wx-1);
132 const Float_t dy = 0.5*(hy-1);
133
134 fWidth = wx;
135
136 MGeomCam cam(wx*hy, 1);
137
138 for (int x=0; x<wx; x++)
139 for (int y=0; y<hy; y++)
140 {
141 Float_t x0 = TMath::Odd(y) ? x-0.25 : x+0.25;
142
143 cam.SetAt(x + y*fWidth, MGeomPix(x0-dx, (y-dy)*0.866, 1));
144 }
145
146
147 cam.InitGeometry();
148
149 SetGeometry(cam);
150}
151
152// --------------------------------------------------------------------------
153//
154// Get index of pixel with position px, py
155//
156Int_t MagicJamEditor::GetPixelIndexFlt(Float_t px, Float_t py) const
157{
158 if (fNcells<=1)
159 return -1;
160
161 Int_t i;
162 for (i=0; i<fNcells-2; i++)
163 {
164 if ((*fGeomCam)[i].IsInside(px, py))
165 return i;
166 }
167 return -1;
168}
169
170// --------------------------------------------------------------------------
171//
172// Open the MagicJam editor. Load a game with name name.
173//
174MagicJamEditor::MagicJamEditor(const char *name) : fImage(NULL)
175{
176 InitGeom(20, 20);
177
178 SetBit(kNoLegend);
179 SetBit(kNoScale);
180
181 Draw();
182
183 gPad->SetEditable(kFALSE);
184
185 if (name)
186 LoadGame(name);
187}
188
189// --------------------------------------------------------------------------
190//
191// Delete fImage
192//
193MagicJamEditor::~MagicJamEditor()
194{
195 if (fImage)
196 delete fImage;
197}
198
199// --------------------------------------------------------------------------
200//
201// Change width and height of pad. Preserve contents.
202//
203void MagicJamEditor::SetWidthHeight(Int_t dx, Int_t dy)
204{
205 TNtuple tup("", "", "x:y");
206 tup.SetDirectory(0);
207
208 for (UInt_t i=0; i<GetNumPixels(); i++)
209 {
210 if (IsUsed(i))
211 tup.Fill((*fGeomCam)[i].GetX(), (*fGeomCam)[i].GetY());
212 }
213 InitGeom(dx, dy);
214
215 fEntries=0;
216 for (int i=0; i<tup.GetEntries(); i++)
217 {
218 tup.GetEntry(i);
219 const Int_t idx = GetPixelIndexFlt(tup.GetArgs()[0], tup.GetArgs()[1]);
220 if (idx>=0)
221 {
222 SetUsed(idx);
223 fEntries++;
224 }
225 }
226}
227
228// --------------------------------------------------------------------------
229//
230// Save the current game
231//
232void MagicJamEditor::SaveGame(const char *name)
233{
234 ofstream fout(name);
235 if (!fout)
236 {
237 cout << "Cannot open file " << name << ": " << strerror(errno) << endl;
238 return;
239 }
240
241 for (UInt_t i=0; i<GetNumPixels(); i++)
242 if (IsUsed(i))
243 fout << i%fWidth << " " << i/fWidth << endl;
244
245 SetName(name);
246
247}
248
249// --------------------------------------------------------------------------
250//
251// Load a game
252//
253void MagicJamEditor::LoadGame(const char *name)
254{
255 InitGeom(1,1);
256 Reset();
257
258 ifstream fin(name);
259 if (!fin)
260 {
261 cout << "Cannot open file " << name << ": " << strerror(errno) << endl;
262 return;
263 }
264
265 Int_t maxx=-INT_MAX;
266 Int_t maxy=-INT_MAX;
267 Int_t minx= INT_MAX;
268 Int_t miny= INT_MAX;
269
270 TNtuple tup("", "", "x:y");
271 tup.SetDirectory(0);
272
273 while (1)
274 {
275 Int_t x,y;
276 fin >> x >> y;
277 if (!fin)
278 break;
279
280 tup.Fill(x, y);
281
282 maxx = TMath::Max(maxx, x);
283 maxy = TMath::Max(maxy, y);
284 minx = TMath::Min(minx, x);
285 miny = TMath::Min(miny, y);
286 }
287
288 if (tup.GetEntries()==0)
289 {
290 cout << "File " << name << " contains no entries!" << endl;
291 return;
292 }
293
294 if (TMath::Odd(miny))
295 miny--;
296
297 InitGeom((maxx-minx)+1, (maxy-miny)+1);
298
299 for (int i=0; i<tup.GetEntries(); i++)
300 {
301 tup.GetEntry(i);
302
303 const Int_t x = TMath::Nint(tup.GetArgs()[0]) - minx;
304 const Int_t y = TMath::Nint(tup.GetArgs()[1]) - miny;
305 SetUsed(x + y*fWidth);
306 }
307
308 fEntries=tup.GetEntries();;
309
310 SetName(name);
311}
312
313void MagicJamEditor::ShowImageAsBackground(const char *name)
314{
315 if (fImage)
316 delete fImage;
317
318 fImage = new TASImage(name);
319 if (!fImage->IsValid())
320 {
321 delete fImage;
322 fImage = NULL;
323 return;
324 }
325
326 fImage->SetEditable(kFALSE);
327
328 SetFillStyle(4000);
329}
330
331void MagicJamEditor::RemoveBackgroundImage()
332{
333 if (fImage)
334 {
335 delete fImage;
336 fImage=NULL;
337 }
338
339 SetFillStyle(1001);
340}
341
342// --------------------------------------------------------------------------
343//
344// Paint the game pad
345//
346void MagicJamEditor::Paint(Option_t *o)
347{
348 TString str = Form("Jam Editor pad %dx%d", fWidth, GetNumPixels()/fWidth);
349 SetTitle(str);
350
351 Float_t maxx = 0;
352 Float_t minx = 0;
353 Float_t maxy = 0;
354 Float_t miny = 0;
355
356 for (UInt_t i=0; i<GetNumPixels(); i++)
357 {
358 const Float_t x = (*fGeomCam)[i].GetX();
359 const Float_t y = (*fGeomCam)[i].GetY();
360
361 maxx = TMath::Max(maxx, x);
362 minx = TMath::Min(minx, x);
363 maxy = TMath::Max(maxy, y);
364 miny = TMath::Min(miny, y);
365 }
366
367 if (fImage)
368 {
369 const Float_t r = fGeomCam->GetMaxRadius();
370
371 MH::SetPadRange(-r*1.02, -r*1.02, TestBit(kNoLegend) ? r : 1.15*r, r*1.2);
372
373 Double_t x1, y1, x2, y2;
374 gPad->GetRange(x1, y1, x2, y2);
375
376 gPad->SetLeftMargin ( (minx-x1)/(x2-x1));
377 gPad->SetBottomMargin( (miny-y1)/(y2-y1));
378 gPad->SetRightMargin (1 - (maxx-x1)/(x2-x1));
379 gPad->SetTopMargin (1 - (maxy-y1)/(y2-y1));
380
381 fImage->Paint();
382 }
383
384 gStyle->SetOptStat(11);
385 MHCamera::Paint(o);
386
387 TBox box;
388 box.SetLineColor(kBlack);
389 box.SetFillStyle(0);
390 box.PaintBox(minx-1, miny-1, maxx+1, maxy+1);
391
392 TLine l;
393 //l.SetLineStyle(kDashed);
394 l.SetLineColor(15);
395 l.PaintLine(0, miny, 0, maxy);
396 l.PaintLine(minx, 0, maxx, 0);
397}
398
399// --------------------------------------------------------------------------
400//
401// Call MHCamera Draw connect a signal to catch the keynoard events
402//
403void MagicJamEditor::Draw(Option_t *o)
404{
405 MHCamera::Draw();
406
407 // This seems to be necessary due to the pad-in-pad geometry
408 // otherwise I don't get the information about the keys pressed
409 gPad->GetCanvas()->Connect("ProcessedEvent(Int_t,Int_t,Int_t,TObject*)",
410 "MagicJamEditor", this,
411 "EventInfo(Int_t,Int_t,Int_t,TObject*)");
412}
413
414// --------------------------------------------------------------------------
415//
416// Process the keyboard events
417//
418void MagicJamEditor::EventInfo(Int_t event, Int_t px, Int_t py, TObject *o)
419{
420 if (event==kKeyPress)
421 {
422 switch (py)
423 {
424 case kKey_Left:
425 Move(-1, 0);
426 break;
427
428 case kKey_Right:
429 Move(1, 0);
430 break;
431
432 case kKey_Up:
433 Move(0, 1);
434 break;
435
436 case kKey_Down:
437 Move(0, -1);
438 break;
439
440 default:
441 return;
442 }
443
444 TVirtualPad *p = dynamic_cast<TVirtualPad*>(o);
445 if (p)
446 {
447 p->Modified();
448 p->Update();
449 }
450 }
451}
452
453// --------------------------------------------------------------------------
454//
455// Execute mouse events
456//
457void MagicJamEditor::ExecuteEvent(Int_t event, Int_t px, Int_t py)
458{
459 const Int_t idx = GetPixelIndex(px, py);
460 if (idx<0)
461 return;
462
463 switch (event)
464 {
465 case kButton1Down:
466 if (IsUsed(idx))
467 {
468 ResetUsed(idx);
469 fEntries--;
470 }
471 else
472 {
473 SetUsed(idx);
474 fEntries++;
475 }
476 break;
477
478 case kButton1Motion:
479 if (!IsUsed(idx))
480 {
481 SetUsed(idx);
482 fEntries++;
483 }
484 break;
485
486 default:
487 return;
488 }
489
490 gPad->Modified();
491 gPad->Update();
492}
493
494
495// -------------------------------------------------------------------------
496// MagicJam -- the Game
497// -------------------------------------------------------------------------
498
499// --------------------------------------------------------------------------
500//
501// Fill 1 in a single pixel. If the pixel has more content than neighbors
502// it overflows into its neighbors. Called recursivly.
503//
504void MagicJam::FillPix(Int_t idx)
505{
506 if (CountPlayers()==1)
507 return;
508
509 const Int_t newval = fBinEntries[idx+1]+1;
510
511 const MGeom &gpix = (*fGeomCam)[idx];
512 const Int_t n = gpix.GetNumNeighbors();
513
514 SetBinContent(idx+1, fNumPlayer);
515 SetUsed(idx);
516
517 if (newval <= n)
518 {
519 fBinEntries[idx+1] = newval;
520 return;
521 }
522
523 fEntries -= n;
524 fBinEntries[idx+1] = 1;
525
526 for (int i=0; i<n; i++)
527 FillPix(gpix.GetNeighbor(i));
528
529 gPad->Modified();
530 gPad->Update();
531}
532
533// --------------------------------------------------------------------------
534//
535// Count tiles of player
536//
537Int_t MagicJam::CountPlayer(Int_t player) const
538{
539 Int_t sum = 0;
540 for (int i=0; i<GetNbinsX(); i++)
541 if (IsUsed(i) && TMath::Nint(GetBinContent(i+1))==player)
542 sum += fBinEntries[i+1];
543 return sum;
544}
545
546// --------------------------------------------------------------------------
547//
548// Count number of players still able to move
549//
550Int_t MagicJam::CountPlayers() const
551{
552 if (GetEntries()<=fNumPlayers)
553 return 0;
554
555 Int_t cnt=0;
556 for (int i=0; i<fNumPlayers; i++)
557 if (CountPlayer(i)>0)
558 cnt++;
559
560 return cnt;
561}
562
563// --------------------------------------------------------------------------
564//
565// Start MagicJam. Loads the default game jam.txt and initializes a
566// two player game
567//
568MagicJam::MagicJam(const char *jam, MagicJam *game) : fNumPlayers(0), fGame(game)
569{
570 SetTitle("Magic Jam (game)");
571
572 SetBit(kNoLegend);
573 SetBit(kNoScale);
574 SetBit(kMustCleanup);
575
576 LoadGame(jam);
577
578 gInterpreter->DeleteGlobal(this);
579 gROOT->GetListOfCleanups()->Add(this);
580
581 if (fGame!=NULL)
582 {
583 SetBit(kNoContextMenu);
584 SetBit(kNoStats);
585 return;
586 }
587
588 if (!fGeomCam)
589 return;
590
591 SetNumPlayers(2);
592 SetMinMax(-0.5, 9.5);
593
594 Draw();
595 gPad->SetEditable(kFALSE);
596}
597
598// --------------------------------------------------------------------------
599//
600// Remove fGame if it was deleted
601//
602void MagicJam::RecursiveRemove(TObject *obj)
603{
604 if (fGame==obj)
605 fGame=0;
606}
607
608// --------------------------------------------------------------------------
609//
610// Set a new number of players. Restarts the game
611//
612void MagicJam::SetNumPlayers(Byte_t n)
613{
614 if (n<2 || n>9)
615 return;
616
617 fNumPlayers = n;
618 fNumPlayer = 0;
619
620 Reset();
621}
622
623// --------------------------------------------------------------------------
624//
625// Loads a new geometry (game). Restarts the game.
626//
627void MagicJam::LoadGame(const char *name)
628{
629 /*
630 if (gPad)
631 {
632 static const char *gOpenTypes[] =
633 {
634 "Template files", "*.txt",
635 "All files", "*",
636 NULL, NULL
637 };
638
639 static TString dir(".");
640
641 TGFileInfo fi; // fFileName and fIniDir deleted in ~TGFileInfo
642
643 fi.fFileTypes = (const char**)gOpenTypes;
644 fi.fIniDir = StrDup(dir);
645
646 dlg = new TGFileDialog(0, 0, kFDOpen, &fi);
647
648 // Checks is meanwhile the game has been closed!
649 if (!gPad)
650 return;
651
652 cout << "done" << endl;
653
654 cout << gPad << endl;
655
656 if (!fi.fFilename || gPad==NULL)
657 return;
658
659 cout << "test" << endl;
660
661 dir = fi.fIniDir;
662 name = fi.fFilename;
663 }
664 //if (!gROOT->GetListOfSpecials()->FindObject(this))
665 // return;
666
667 cout << "Done." << endl;
668 */
669 //***
670
671
672
673 ifstream fin(name);
674 if (!fin)
675 {
676 cout << "Cannot open file " << name << ": " << strerror(errno) << endl;
677 return;
678 }
679
680 Int_t maxx=-INT_MAX;
681 Int_t maxy=-INT_MAX;
682 Int_t minx= INT_MAX;
683 Int_t miny= INT_MAX;
684
685 TNtuple tup("", "", "x:y");
686 tup.SetDirectory(0);
687
688 while (1)
689 {
690 Int_t x,y;
691 fin >> x >> y;
692 if (!fin)
693 break;
694
695 tup.Fill(x, y);
696
697 maxx = TMath::Max(maxx, x);
698 maxy = TMath::Max(maxy, y);
699 minx = TMath::Min(minx, x);
700 miny = TMath::Min(miny, y);
701 }
702
703 if (tup.GetEntries()==0)
704 {
705 cout << "File " << name << " contains no entries!" << endl;
706 return;
707 }
708
709 MGeomCam cam(tup.GetEntries());
710
711 for (int i=0; i<tup.GetEntries(); i++)
712 {
713 tup.GetEntry(i);
714
715 const Int_t x = TMath::Nint(tup.GetArgs()[0]);
716 const Int_t y = TMath::Nint(tup.GetArgs()[1]);
717
718 Float_t dx = -minx-0.5*(maxx-minx+1);
719 Float_t dy = -miny-0.5*(maxy-miny+1);
720
721 dx += TMath::Odd(y) ? x-0.25 : x+0.25;
722 dy += y;
723
724 cam.SetAt(i, MGeomPix(dx, dy*0.866));
725 }
726
727 for (UInt_t i=0; i<cam.GetNumPixels(); i++)
728 {
729 Int_t nn[6] = { -1, -1, -1, -1, -1, -1 };
730 Int_t idx=0;
731
732 for (UInt_t j=0; j<cam.GetNumPixels(); j++)
733 if (i!=j && cam.GetDist(i,j)<1.5)
734 nn[idx++] = j;
735
736 cam[i].SetNeighbors(nn[0], nn[1], nn[2], nn[3], nn[4], nn[5]);
737 }
738
739 cam.InitGeometry();
740
741 SetGeometry(cam);
742
743 SetName(name);
744 Reset();
745}
746
747// --------------------------------------------------------------------------
748//
749// Restart the game.
750//
751void MagicJam::Reset(Option_t *o)
752{
753 MHCamera::Reset("");
754
755 if (fNumPlayers==0)
756 {
757 SetAllUsed();
758 return;
759 }
760
761 const Int_t max = TMath::Max((Int_t)GetNumPixels()/25, 1);
762 for (Int_t i=0; i<fNumPlayers; i++)
763 {
764 for (Int_t x=0; x<max; x++)
765 {
766 const Int_t idx = gRandom->Integer(GetNumPixels()-1);
767
768 if (IsUsed(idx))
769 {
770 x--;
771 continue;
772 }
773
774 SetUsed(idx);
775 SetBinContent(idx+1, i);
776 fBinEntries[idx+1] = 1;
777 }
778 }
779}
780
781// --------------------------------------------------------------------------
782//
783// Star an editor to make your own game.
784//
785void MagicJam::StartEditor() const
786{
787 TCanvas *c=new TCanvas;
788
789 c->SetName("Editor");
790 c->SetTitle("MagicJam Editor");
791
792 MagicJamEditor *build=new MagicJamEditor;
793
794 build->SetBit(kCanDelete);
795}
796
797// --------------------------------------------------------------------------
798//
799// Open the current game in the editor.
800//
801void MagicJam::OpenInEditor() const
802{
803 TCanvas *c=new TCanvas;
804
805 c->SetName("Editor");
806 c->SetTitle("MagicJam Editor");
807
808 MagicJamEditor *build=new MagicJamEditor(GetName());
809
810 build->SetBit(kCanDelete);
811}
812
813// --------------------------------------------------------------------------
814//
815// Show the Jam games of this directory
816//
817void MagicJam::ShowDirectory(const char *dir)
818{
819 MDirIter Next(dir, "*.jam");
820
821 TList list;
822
823 TString file;
824 while (1)
825 {
826 file=Next();
827 if (file.IsNull())
828 break;
829
830 MagicJam *jam = new MagicJam(file, this);
831 if (jam->GetNumPixels()==0)
832 {
833 delete jam;
834 continue;
835 }
836 list.Add(jam);
837 }
838
839 const Int_t n1 = TMath::Nint(TMath::Ceil(list.GetEntries()/3.));
840 const Int_t n2 = TMath::Nint(TMath::Ceil((float)list.GetEntries()/n1));
841
842 TCanvas *c = new TCanvas;
843 c->SetBorderMode(0);
844 c->SetFillColor(kWhite);
845 c->Divide(n1, n2, 0, 0);
846 c->SetBit(kNoContextMenu);
847 c->SetBit(kCannotPick);
848
849 Int_t i=0;
850
851 TObject *o=0;
852
853 TIter NextObj(&list);
854
855 while ((o=NextObj()))
856 {
857 list.Remove(o);
858
859 c->cd(++i);
860 gPad->SetFillColor(kWhite);
861 o->SetBit(kCanDelete);
862 o->Draw();
863 gPad->SetBit(kCannotPick);
864 }
865
866 // Delete empty pads
867 for (; i<=n1*n2; i++)
868 delete c->GetPad(i);
869}
870
871// --------------------------------------------------------------------------
872//
873// Process mouse events
874//
875void MagicJam::ExecuteEvent(Int_t event, Int_t px, Int_t py)
876{
877 if (fNumPlayers==0) // We are in ShowDirectory-Mode
878 {
879 if (event!=kButton1Down)
880 return;
881
882 if (fGame)
883 {
884 // Do a simple search for the pad containing fGame
885 TIter Next(gROOT->GetListOfCanvases());
886 TCanvas *c=0;
887 while((c=(TCanvas*)Next()))
888 {
889 TVirtualPad *pad1 = c->GetPad(1);
890 if (!pad1)
891 continue;
892
893 if (!pad1->GetListOfPrimitives()->FindObject(fGame))
894 continue;
895
896 fGame->LoadGame(GetName());
897
898 pad1->Modified();
899 pad1->Update();
900 return;
901 }
902 }
903
904 // No pad found. Open new canvas for it
905 new TCanvas;
906 new MagicJam(GetName());
907
908 return;
909 }
910
911 if (CountPlayers()==1) // We already have a winner
912 return;
913
914 if (event==kButton1Down)
915 {
916 const Int_t idx = GetPixelIndex(px, py);
917 if (idx<0)
918 return;
919
920 if (IsUsed(idx) && TMath::Nint(GetBinContent(idx+1))!=fNumPlayer)
921 {
922 const Int_t col = gPad->GetFillColor();
923
924 gPad->SetFillColor(kRed);
925 gPad->Modified();
926 gPad->Update();
927
928 gSystem->Sleep(250);
929
930 gPad->SetFillColor(col);
931 gPad->Modified();
932 gPad->Update();
933 return;
934 }
935
936 FillPix(idx);
937
938 do
939 {
940 fNumPlayer++;
941 fNumPlayer %= fNumPlayers;
942 }
943 while (CountPlayers()>1 && CountPlayer(fNumPlayer)==0);
944
945 gPad->Modified();
946 gPad->Update();
947 }
948}
949
950// --------------------------------------------------------------------------
951//
952// Paint game pad
953//
954void MagicJam::Paint(Option_t *o)
955{
956 if (GetNumPixels()==0)
957 return;
958
959 gStyle->SetOptStat(11);
960
961 Int_t palette[50] =
962 {
963 4, 4, 4, 4, 4, // light blue
964 3, 3, 3, 3, 3, // light green
965 6, 6, 6, 6, 6, // magenta
966 5, 5, 5, 5, 5, // yellow
967 7, 7, 7, 7, 7, // cyan
968 //8, 8, 8, 8, 8, // dark green
969 //11, 11, 11, 11,11, // light gray
970 12, 12, 12, 12,12, // dark gray
971 1, 1, 1, 1, 1, // black
972 46, 46, 46, 46, 46,
973 51, 51, 51, 51, 51, // brown
974 };
975
976 gStyle->SetPalette(50, palette);
977 MHCamera::Paint(o);
978
979 TText txt;
980 txt.SetTextAlign(13); // left/bottom
981 txt.SetTextSize(0.03);
982
983 const Double_t range = fGeomCam->GetMaxRadius();
984
985 Int_t max = 0;
986 Int_t num = 0;
987 Int_t pos = 0;
988 for (int i=0; i<fNumPlayers; i++)
989 {
990 const Int_t cnt = CountPlayer(i);
991
992 if (cnt>max)
993 {
994 max = cnt;
995 num = i;
996 }
997 if (cnt==0)
998 continue;
999
1000 TString str = Form("Player #%d: %d %s", i+1, cnt, i==fNumPlayer?"<*>":"");
1001
1002 txt.SetTextColor(GetColor(i, fMinimum, fMaximum, kFALSE));
1003 txt.PaintText(-range*0.95, range-pos*range*0.06, str);
1004
1005 pos++;
1006 }
1007
1008 if (CountPlayers()==1)
1009 {
1010 TString str = "And the Winner... is... player #";
1011 str += Form("%d (Score=%d)", num+1, max);
1012 txt.SetTextColor(kRed); // white
1013 txt.SetTextAlign(22); // centered/centered
1014 txt.SetTextSize(0.05); // white
1015 txt.PaintText(0, 0, str);
1016 }
1017
1018 if (fNumPlayers==0)
1019 {
1020 txt.SetTextSize(0.075);
1021 txt.SetTextColor(kBlack);
1022
1023 txt.SetTextAlign(13); // left/top
1024 txt.PaintTextNDC(0.02, 0.99, GetName());
1025
1026 //txt.SetTextAlign(11); // left/bottom
1027 //txt.PaintTextNDC(0.01, 0.01, Form("%d", GetNumPixels()));
1028 txt.PaintTextNDC(0.02, 0.91, Form("%d", GetNumPixels()));
1029 }
1030}
1031
1032// --------------------------------------------------------------------------
1033//
1034// Calls draw of the base class MHCamera with the necessary options
1035//
1036void MagicJam::Draw(Option_t *o)
1037{
1038 MHCamera::Draw(fNumPlayers>0 ? "pixelentries nopal" : "nopal");
1039 gPad->SetBit(kCannotPick);
1040}
Note: See TracBrowser for help on using the repository browser.