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

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