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

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