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

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