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

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