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

Last change on this file since 9203 was 9195, checked in by tbretz, 16 years ago
*** empty log message ***
File size: 22.8 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of MARS, the MAGIC Analysis and Reconstruction
5! * Software. It is distributed to you in the hope that it can be a useful
6! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
7! * It is distributed WITHOUT ANY WARRANTY.
8! *
9! * Permission to use, copy, modify and distribute this software and its
10! * documentation for any purpose is hereby granted without fee,
11! * provided that the above copyright notice appear in all copies and
12! * that both that copyright notice and this permission notice appear
13! * in supporting documentation. It is provided "as is" without express
14! * or implied warranty.
15! *
16!
17!
18! Author(s): Thomas Bretz, 9/2005 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2005-2008
21!
22!
23\* ======================================================================== */
24
25/////////////////////////////////////////////////////////////////////////////
26//
27// MagicJam
28//
29// Jam is a multi player game. It is controlled by its context menu (click
30// with the right mouse button on one of the pixels in the game pad).
31//
32// Start the game with:
33// MagicJam jam;
34//
35// Rules:
36// MagicJam is a multiplayer game. The aim is to own the full game pad.
37// Ech pixel in the pad can contain as many entries as it has neighbors.
38// If it has more entries than neighbors it overflows into its neighbors.
39// All pixels into which such an overflow occures will be captured by
40// the current player. Player by player will be able to increase the
41// entry in one pixel by one. Increase the contents of an empty pixel to
42// one or by one in an owned pixel. The player who once will own the
43// all pixels will win.
44//
45// Editor:
46// To edit or create a new game start the editor from the context menu
47// of MagicJam. The editor is also controlled from its context menu.
48// Use the curso keys to shift your game.
49// Warning: You MUST create a single-island game. Games which have two
50// islands might result in edless loops. (Currently there is no check!)
51//
52/////////////////////////////////////////////////////////////////////////////
53#include "MagicJam.h"
54
55#include <climits> // INT_MAX (Ubuntu 8.10)
56
57#include <iostream>
58#include <fstream>
59
60#include <errno.h>
61
62#include <KeySymbols.h>
63
64#include <TMath.h>
65#include <TRandom.h>
66
67#include <TBox.h>
68#include <TLine.h>
69#include <TText.h>
70
71#include <TStyle.h>
72#include <TSystem.h>
73
74#include <TNtuple.h>
75#include <TASImage.h>
76#include <TInterpreter.h>
77#include <TGFileDialog.h>
78
79#include "MHexagon.h"
80#include "MGeomCam.h"
81#include "MGeomPix.h"
82
83#include "MDirIter.h"
84
85ClassImp(MagicJamAbc);
86ClassImp(MagicJamEditor);
87ClassImp(MagicJam);
88
89using namespace std;
90
91// -------------------------------------------------------------------------
92// The editor for MagicJam
93// -------------------------------------------------------------------------
94
95// --------------------------------------------------------------------------
96//
97// Move the contents of the pad
98//
99void MagicJamEditor::Move(int dx, int dy)
100{
101 const TArrayC cpy(fUsed);
102
103 Int_t h = cpy.GetSize()/fWidth;
104
105 for (int i=0; i<cpy.GetSize(); i++)
106 {
107 Int_t x = i%fWidth;
108 Int_t y = i/fWidth;
109
110 x += dx + fWidth;
111 y += dy*2 + h;
112
113 x %= fWidth;
114 y %= h;
115
116 fUsed[x+y*fWidth] = cpy[i];
117 }
118 gPad->GetPad(1)->Modified();
119 gPad->GetPad(1)->Update();
120 gPad->Modified();
121 gPad->Update();
122}
123
124// --------------------------------------------------------------------------
125//
126// Initialize the pad with size wx, hy
127//
128void MagicJamEditor::InitGeom(int wx, int hy)
129{
130 const Float_t dx = 0.5*(wx-1);
131 const Float_t dy = 0.5*(hy-1);
132
133 fWidth = wx;
134
135 MGeomCam cam(wx*hy, 1);
136
137 for (int x=0; x<wx; x++)
138 for (int y=0; y<hy; y++)
139 {
140 Float_t x0 = TMath::Odd(y) ? x-0.25 : x+0.25;
141
142 cam[x + y*fWidth].Set(x0-dx, (y-dy)*0.866, 1);
143 }
144
145 SetGeometry(cam);
146}
147
148// --------------------------------------------------------------------------
149//
150// Get index of pixel with position px, py
151//
152Int_t MagicJamEditor::GetPixelIndexFlt(Float_t px, Float_t py) const
153{
154 if (fNcells<=1)
155 return -1;
156
157 Int_t i;
158 for (i=0; i<fNcells-2; i++)
159 {
160 MHexagon hex((*fGeomCam)[i]);
161 if (hex.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 SetRange();
369
370 Double_t x1, y1, x2, y2;
371 gPad->GetRange(x1, y1, x2, y2);
372
373 gPad->SetLeftMargin ( (minx-x1)/(x2-x1));
374 gPad->SetBottomMargin( (miny-y1)/(y2-y1));
375 gPad->SetRightMargin (1 - (maxx-x1)/(x2-x1));
376 gPad->SetTopMargin (1 - (maxy-y1)/(y2-y1));
377
378 fImage->Paint();
379 }
380
381 gStyle->SetOptStat(11);
382 MHCamera::Paint(o);
383
384 TBox box;
385 box.SetLineColor(kBlack);
386 box.SetFillStyle(0);
387 box.PaintBox(minx-1, miny-1, maxx+1, maxy+1);
388
389 TLine l;
390 //l.SetLineStyle(kDashed);
391 l.SetLineColor(15);
392 l.PaintLine(0, miny, 0, maxy);
393 l.PaintLine(minx, 0, maxx, 0);
394}
395
396// --------------------------------------------------------------------------
397//
398// Call MHCamera Draw connect a signal to catch the keynoard events
399//
400void MagicJamEditor::Draw(Option_t *o)
401{
402 MHCamera::Draw();
403
404 // This seems to be necessary due to the pad-in-pad geometry
405 // otherwise I don't get the information about the keys pressed
406 gPad->GetCanvas()->Connect("ProcessedEvent(Int_t,Int_t,Int_t,TObject*)",
407 "MagicJamEditor", this,
408 "EventInfo(Int_t,Int_t,Int_t,TObject*)");
409}
410
411// --------------------------------------------------------------------------
412//
413// Process the keyboard events
414//
415void MagicJamEditor::EventInfo(Int_t event, Int_t px, Int_t py, TObject *o)
416{
417 if (event==kKeyPress)
418 {
419 switch (py)
420 {
421 case kKey_Left:
422 Move(-1, 0);
423 break;
424
425 case kKey_Right:
426 Move(1, 0);
427 break;
428
429 case kKey_Up:
430 Move(0, 1);
431 break;
432
433 case kKey_Down:
434 Move(0, -1);
435 break;
436
437 default:
438 return;
439 }
440
441 TVirtualPad *p = dynamic_cast<TVirtualPad*>(o);
442 if (p && p->GetPad(1))
443 {
444 p->GetPad(1)->Modified();
445 p->GetPad(1)->Update();
446 }
447 }
448}
449
450// --------------------------------------------------------------------------
451//
452// Execute mouse events
453//
454void MagicJamEditor::ExecuteEvent(Int_t event, Int_t px, Int_t py)
455{
456 const Int_t idx = GetPixelIndex(px, py);
457 if (idx<0)
458 return;
459
460 switch (event)
461 {
462 case kButton1Down:
463 if (IsUsed(idx))
464 {
465 ResetUsed(idx);
466 fEntries--;
467 }
468 else
469 {
470 SetUsed(idx);
471 fEntries++;
472 }
473 break;
474
475 case kButton1Motion:
476 if (!IsUsed(idx))
477 {
478 SetUsed(idx);
479 fEntries++;
480 }
481 break;
482
483 default:
484 return;
485 }
486
487 gPad->Modified();
488 gPad->Update();
489}
490
491
492// -------------------------------------------------------------------------
493// MagicJam -- the Game
494// -------------------------------------------------------------------------
495
496// --------------------------------------------------------------------------
497//
498// Fill 1 in a single pixel. If the pixel has more content than neighbors
499// it overflows into its neighbors. Called recursivly.
500//
501void MagicJam::FillPix(Int_t idx)
502{
503 if (CountPlayers()==1)
504 return;
505
506 const Int_t newval = fBinEntries[idx+1]+1;
507
508 const MGeomPix &gpix = (*fGeomCam)[idx];
509 const Int_t n = gpix.GetNumNeighbors();
510
511 SetBinContent(idx+1, fNumPlayer);
512 SetUsed(idx);
513
514 if (newval <= n)
515 {
516 fBinEntries[idx+1] = newval;
517 return;
518 }
519
520 fEntries -= n;
521 fBinEntries[idx+1] = 1;
522
523 for (int i=0; i<n; i++)
524 FillPix(gpix.GetNeighbor(i));
525
526 gPad->Modified();
527 gPad->Update();
528}
529
530// --------------------------------------------------------------------------
531//
532// Count tiles of player
533//
534Int_t MagicJam::CountPlayer(Int_t player) const
535{
536 Int_t sum = 0;
537 for (int i=0; i<GetNbinsX(); i++)
538 if (IsUsed(i) && TMath::Nint(GetBinContent(i+1))==player)
539 sum += fBinEntries[i+1];
540 return sum;
541}
542
543// --------------------------------------------------------------------------
544//
545// Count number of players still able to move
546//
547Int_t MagicJam::CountPlayers() const
548{
549 if (GetEntries()<=fNumPlayers)
550 return 0;
551
552 Int_t cnt=0;
553 for (int i=0; i<fNumPlayers; i++)
554 if (CountPlayer(i)>0)
555 cnt++;
556
557 return cnt;
558}
559
560// --------------------------------------------------------------------------
561//
562// Start MagicJam. Loads the default game jam.txt and initializes a
563// two player game
564//
565MagicJam::MagicJam(const char *jam, MagicJam *game) : fNumPlayers(0), fGame(game)
566{
567 SetTitle("Magic Jam (game)");
568
569 SetBit(kNoLegend);
570 SetBit(kNoScale);
571 SetBit(kMustCleanup);
572
573 LoadGame(jam);
574
575 gInterpreter->DeleteGlobal(this);
576 gROOT->GetListOfCleanups()->Add(this);
577
578 if (fGame!=NULL)
579 {
580 SetBit(kNoContextMenu);
581 SetBit(kNoStats);
582 return;
583 }
584
585 if (!fGeomCam)
586 return;
587
588 SetNumPlayers(2);
589 SetMinMax(-0.5, 9.5);
590
591 Draw();
592 gPad->SetEditable(kFALSE);
593}
594
595// --------------------------------------------------------------------------
596//
597// Remove fGame if it was deleted
598//
599void MagicJam::RecursiveRemove(TObject *obj)
600{
601 if (fGame==obj)
602 fGame=0;
603}
604
605// --------------------------------------------------------------------------
606//
607// Set a new number of players. Restarts the game
608//
609void MagicJam::SetNumPlayers(Byte_t n)
610{
611 if (n<2 || n>9)
612 return;
613
614 fNumPlayers = n;
615 fNumPlayer = 0;
616
617 Reset();
618}
619
620// --------------------------------------------------------------------------
621//
622// Loads a new geometry (game). Restarts the game.
623//
624void MagicJam::LoadGame(const char *name)
625{
626 /*
627 if (gPad)
628 {
629 static const char *gOpenTypes[] =
630 {
631 "Template files", "*.txt",
632 "All files", "*",
633 NULL, NULL
634 };
635
636 static TString dir(".");
637
638 TGFileInfo fi; // fFileName and fIniDir deleted in ~TGFileInfo
639
640 fi.fFileTypes = (const char**)gOpenTypes;
641 fi.fIniDir = StrDup(dir);
642
643 dlg = new TGFileDialog(0, 0, kFDOpen, &fi);
644
645 // Checks is meanwhile the game has been closed!
646 if (!gPad)
647 return;
648
649 cout << "done" << endl;
650
651 cout << gPad << endl;
652
653 if (!fi.fFilename || gPad==NULL)
654 return;
655
656 cout << "test" << endl;
657
658 dir = fi.fIniDir;
659 name = fi.fFilename;
660 }
661 //if (!gROOT->GetListOfSpecials()->FindObject(this))
662 // return;
663
664 cout << "Done." << endl;
665 */
666 //***
667
668
669
670 ifstream fin(name);
671 if (!fin)
672 {
673 cout << "Cannot open file " << name << ": " << strerror(errno) << endl;
674 return;
675 }
676
677 Int_t maxx=-INT_MAX;
678 Int_t maxy=-INT_MAX;
679 Int_t minx= INT_MAX;
680 Int_t miny= INT_MAX;
681
682 TNtuple tup("", "", "x:y");
683 tup.SetDirectory(0);
684
685 while (1)
686 {
687 Int_t x,y;
688 fin >> x >> y;
689 if (!fin)
690 break;
691
692 tup.Fill(x, y);
693
694 maxx = TMath::Max(maxx, x);
695 maxy = TMath::Max(maxy, y);
696 minx = TMath::Min(minx, x);
697 miny = TMath::Min(miny, y);
698 }
699
700 if (tup.GetEntries()==0)
701 {
702 cout << "File " << name << " contains no entries!" << endl;
703 return;
704 }
705
706 MGeomCam cam(tup.GetEntries());
707
708 for (int i=0; i<tup.GetEntries(); i++)
709 {
710 tup.GetEntry(i);
711
712 const Int_t x = TMath::Nint(tup.GetArgs()[0]);
713 const Int_t y = TMath::Nint(tup.GetArgs()[1]);
714
715 Float_t dx = -minx-0.5*(maxx-minx+1);
716 Float_t dy = -miny-0.5*(maxy-miny+1);
717
718 dx += TMath::Odd(y) ? x-0.25 : x+0.25;
719 dy += y;
720
721 cam[i].Set(dx, dy*0.866);
722 }
723
724 for (UInt_t i=0; i<cam.GetNumPixels(); i++)
725 {
726 Int_t nn[6] = { -1, -1, -1, -1, -1, -1 };
727 Int_t idx=0;
728
729 for (UInt_t j=0; j<cam.GetNumPixels(); j++)
730 if (i!=j && cam.GetDist(i,j)<1.5)
731 nn[idx++] = j;
732
733 cam[i].SetNeighbors(nn[0], nn[1], nn[2], nn[3], nn[4], nn[5]);
734 }
735
736 SetGeometry(cam);
737
738 SetName(name);
739 Reset();
740}
741
742// --------------------------------------------------------------------------
743//
744// Restart the game.
745//
746void MagicJam::Reset(Option_t *o)
747{
748 MHCamera::Reset("");
749
750 if (fNumPlayers==0)
751 {
752 SetAllUsed();
753 return;
754 }
755
756 const Int_t max = TMath::Max((Int_t)GetNumPixels()/25, 1);
757 for (Int_t i=0; i<fNumPlayers; i++)
758 {
759 for (Int_t x=0; x<max; x++)
760 {
761 const Int_t idx = gRandom->Integer(GetNumPixels()-1);
762
763 if (IsUsed(idx))
764 {
765 x--;
766 continue;
767 }
768
769 SetUsed(idx);
770 SetBinContent(idx+1, i);
771 fBinEntries[idx+1] = 1;
772 }
773 }
774}
775
776// --------------------------------------------------------------------------
777//
778// Star an editor to make your own game.
779//
780void MagicJam::StartEditor() const
781{
782 TCanvas *c=new TCanvas;
783
784 c->SetName("Editor");
785 c->SetTitle("MagicJam Editor");
786
787 MagicJamEditor *build=new MagicJamEditor;
788
789 build->SetBit(kCanDelete);
790}
791
792// --------------------------------------------------------------------------
793//
794// Open the current game in the editor.
795//
796void MagicJam::OpenInEditor() const
797{
798 TCanvas *c=new TCanvas;
799
800 c->SetName("Editor");
801 c->SetTitle("MagicJam Editor");
802
803 MagicJamEditor *build=new MagicJamEditor(GetName());
804
805 build->SetBit(kCanDelete);
806}
807
808// --------------------------------------------------------------------------
809//
810// Show the Jam games of this directory
811//
812void MagicJam::ShowDirectory(const char *dir)
813{
814 MDirIter Next(dir, "*.jam");
815
816 TList list;
817
818 TString file;
819 while (1)
820 {
821 file=Next();
822 if (file.IsNull())
823 break;
824
825 MagicJam *jam = new MagicJam(file, this);
826 if (jam->GetNumPixels()==0)
827 {
828 delete jam;
829 continue;
830 }
831 list.Add(jam);
832 }
833
834 const Int_t n1 = TMath::Nint(TMath::Ceil(list.GetEntries()/3.));
835 const Int_t n2 = TMath::Nint(TMath::Ceil((float)list.GetEntries()/n1));
836
837 TCanvas *c = new TCanvas;
838 c->SetBorderMode(0);
839 c->SetFillColor(kWhite);
840 c->Divide(n1, n2, 0, 0);
841 c->SetBit(kNoContextMenu);
842 c->SetBit(kCannotPick);
843
844 Int_t i=0;
845
846 TObject *o=0;
847
848 TIter NextObj(&list);
849
850 while ((o=NextObj()))
851 {
852 list.Remove(o);
853
854 c->cd(++i);
855 gPad->SetFillColor(kWhite);
856 o->SetBit(kCanDelete);
857 o->Draw();
858 gPad->SetBit(kCannotPick);
859 gPad->GetPad(1)->SetBit(kCannotPick);
860 }
861
862 // Delete empty pads
863 for (; i<=n1*n2; i++)
864 delete c->GetPad(i);
865}
866
867// --------------------------------------------------------------------------
868//
869// Process mouse events
870//
871void MagicJam::ExecuteEvent(Int_t event, Int_t px, Int_t py)
872{
873 if (fNumPlayers==0) // We are in ShowDirectory-Mode
874 {
875 if (event!=kButton1Down)
876 return;
877
878 if (fGame)
879 {
880 // Do a simple search for the pad containing fGame
881 TIter Next(gROOT->GetListOfCanvases());
882 TCanvas *c=0;
883 while((c=(TCanvas*)Next()))
884 {
885 TVirtualPad *pad1 = c->GetPad(1);
886 if (!pad1)
887 continue;
888
889 if (!pad1->GetListOfPrimitives()->FindObject(fGame))
890 continue;
891
892 fGame->LoadGame(GetName());
893
894 pad1->Modified();
895 pad1->Update();
896 return;
897 }
898 }
899
900 // No pad found. Open new canvas for it
901 new TCanvas;
902 new MagicJam(GetName());
903
904 return;
905 }
906
907 if (CountPlayers()==1) // We already have a winner
908 return;
909
910 if (event==kButton1Down)
911 {
912 const Int_t idx = GetPixelIndex(px, py);
913 if (idx<0)
914 return;
915
916 if (IsUsed(idx) && TMath::Nint(GetBinContent(idx+1))!=fNumPlayer)
917 {
918 const Int_t col = gPad->GetFillColor();
919
920 gPad->SetFillColor(kRed);
921 gPad->Modified();
922 gPad->Update();
923
924 gSystem->Sleep(250);
925
926 gPad->SetFillColor(col);
927 gPad->Modified();
928 gPad->Update();
929 return;
930 }
931
932 FillPix(idx);
933
934 do
935 {
936 fNumPlayer++;
937 fNumPlayer %= fNumPlayers;
938 }
939 while (CountPlayers()>1 && CountPlayer(fNumPlayer)==0);
940
941 gPad->Modified();
942 gPad->Update();
943 }
944}
945
946// --------------------------------------------------------------------------
947//
948// Paint game pad
949//
950void MagicJam::Paint(Option_t *o)
951{
952 if (GetNumPixels()==0)
953 return;
954
955 gStyle->SetOptStat(11);
956
957 Int_t palette[50] =
958 {
959 4, 4, 4, 4, 4, // light blue
960 3, 3, 3, 3, 3, // light green
961 6, 6, 6, 6, 6, // magenta
962 5, 5, 5, 5, 5, // yellow
963 7, 7, 7, 7, 7, // cyan
964 //8, 8, 8, 8, 8, // dark green
965 //11, 11, 11, 11,11, // light gray
966 12, 12, 12, 12,12, // dark gray
967 1, 1, 1, 1, 1, // black
968 46, 46, 46, 46, 46,
969 51, 51, 51, 51, 51, // brown
970 };
971
972 gStyle->SetPalette(50, palette);
973 MHCamera::Paint(o);
974
975 TText txt;
976 txt.SetTextAlign(13); // left/bottom
977 txt.SetTextSize(0.03);
978
979 const Double_t range = fGeomCam->GetMaxRadius();
980
981 Int_t max = 0;
982 Int_t num = 0;
983 Int_t pos = 0;
984 for (int i=0; i<fNumPlayers; i++)
985 {
986 const Int_t cnt = CountPlayer(i);
987
988 if (cnt>max)
989 {
990 max = cnt;
991 num = i;
992 }
993 if (cnt==0)
994 continue;
995
996 TString str = Form("Player #%d: %d %s", i+1, cnt, i==fNumPlayer?"<*>":"");
997
998 txt.SetTextColor(GetColor(i, fMinimum, fMaximum, kFALSE));
999 txt.PaintText(-range*0.95, range-pos*range*0.06, str);
1000
1001 pos++;
1002 }
1003
1004 if (CountPlayers()==1)
1005 {
1006 TString str = "And the Winner... is... player #";
1007 str += Form("%d (Score=%d)", num+1, max);
1008 txt.SetTextColor(kRed); // white
1009 txt.SetTextAlign(22); // centered/centered
1010 txt.SetTextSize(0.05); // white
1011 txt.PaintText(0, 0, str);
1012 }
1013
1014 if (fNumPlayers==0)
1015 {
1016 txt.SetTextSize(0.075);
1017 txt.SetTextColor(kBlack);
1018
1019 txt.SetTextAlign(13); // left/top
1020 txt.PaintTextNDC(0.02, 0.99, GetName());
1021
1022 //txt.SetTextAlign(11); // left/bottom
1023 //txt.PaintTextNDC(0.01, 0.01, Form("%d", GetNumPixels()));
1024 txt.PaintTextNDC(0.02, 0.91, Form("%d", GetNumPixels()));
1025 }
1026}
1027
1028// --------------------------------------------------------------------------
1029//
1030// Calls draw of the base class MHCamera with the necessary options
1031//
1032void MagicJam::Draw(Option_t *o)
1033{
1034 MHCamera::Draw(fNumPlayers>0 ? "pixelentries nopal" : "nopal");
1035 gPad->SetBit(kCannotPick);
1036}
Note: See TracBrowser for help on using the repository browser.