source: trunk/MagicSoft/Mars/mtools/MagicJam.cc@ 9029

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