source: tags/Mars-V2.2/mtools/MagicJam.cc

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