source: trunk/Mars/mtools/MagicReversi.cc@ 17284

Last change on this file since 17284 was 9369, checked in by tbretz, 16 years ago
*** empty log message ***
File size: 11.8 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, 3/2003 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: CheObs Software Development, 2000-2009
21!
22!
23\* ======================================================================== */
24
25/////////////////////////////////////////////////////////////////////////////
26//
27// MagicReversi
28// ------------
29//
30// Camera Display Games: Reversi
31//
32// Start the game by:
33// MagicReversi reversi;
34//
35// Rules:
36// ------
37//
38// Use the mouse to put a stone at some place. If between your newly
39// placed stone and the next stone (in a row) of your color are stones
40// of other colors this stones are won by you. You can only place a
41// stone if you win at least one stone from your 'enemy'. If you
42// cannot do so, you are skipped. If nobody can make a move anymore
43// the game is over. The player has won who has the most stones in
44// his own color.
45// The present player is indicated by <*>
46// Use the Escape key to abort a game.
47// If the game was aborted or has been stopped youcan access the
48// options in the context menu.
49//
50////////////////////////////////////////////////////////////////////////////
51#include "MagicReversi.h"
52
53#include <iostream>
54
55#include <KeySymbols.h>
56
57#include <TText.h>
58#include <TMarker.h>
59#include <TRandom.h>
60#include <TCanvas.h>
61#include <TClonesArray.h>
62#include <TInterpreter.h>
63
64#include "MH.h"
65
66#include "MGeomPix.h"
67#include "MGeomCamCT1.h"
68#include "MGeomCamMagic.h"
69
70ClassImp(MagicReversi);
71
72using namespace std;
73
74/*
75const Int_t MagicReversi::fColorBombs[7] = {
76 22,
77 kYellow,
78 kGreen,
79 kBlue,
80 kCyan,
81 kMagenta,
82 kRed
83};
84*/
85void MagicReversi::Free()
86{
87 if (!fGeomCam)
88 return;
89
90 fText->Delete();
91 fFlags->Delete();
92
93 delete fText;
94 delete fFlags;
95
96 delete fGeomCam;
97}
98
99void MagicReversi::ChangeCamera()
100{
101 static Bool_t ct1=kFALSE;
102
103 cout << "Change to " << (ct1?"Magic":"CT1") << endl;
104
105 if (ct1)
106 SetNewCamera(new MGeomCamMagic);
107 else
108 SetNewCamera(new MGeomCamCT1);
109
110 ct1 = !ct1;
111
112 Reset();
113}
114
115void MagicReversi::SetNewCamera(MGeomCam *geom)
116{
117 Free();
118
119 //
120 // Set new camera
121 //
122 fGeomCam = geom;
123
124 //
125 // create the hexagons of the display
126 //
127 fNumPixels = fGeomCam->GetNumPixels();
128 fRange = fGeomCam->GetMaxRadius();
129
130 //
131 // Construct all hexagons. Use new-operator with placement
132 //
133// fNumBombs = fNumPixels/5;
134
135 fText = new TClonesArray("TText", fNumPixels);
136 fFlags = new TClonesArray("TMarker", fNumPixels);
137 fColors.Set(fNumPixels);
138
139 for (UInt_t i=0; i<fNumPixels; i++)
140 {
141 const MGeom &pix = (*fGeomCam)[i];
142
143 TText &t = *new ((*fText)[i]) TText;
144 t.SetTextFont(122);
145 t.SetTextAlign(22); // centered/centered
146 t.SetTextSize(0.3*pix.GetT()/fRange);
147#if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06)
148 t.SetBit(kNoContextMenu|kCannotPick);
149#endif
150
151 TMarker &m = *new ((*fFlags)[i]) TMarker(pix.GetX(), pix.GetY(), kOpenStar);
152#if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06)
153 m.SetBit(kNoContextMenu|kCannotPick);
154#endif
155 }
156}
157
158/*
159// ------------------------------------------------------------------------
160//
161// Draw all pixels of the camera
162// (means apend all pixelobjects to the current pad)
163//
164void MagicReversi::DrawHexagons()
165{
166 for (UInt_t i=0; i<fNumPixels; i++)
167 (*this)[i].Draw();
168}
169*/
170
171void MagicReversi::Init()
172{
173 //
174 // Make sure, that the object is destroyed when the canvas/pad is
175 // destroyed. Make also sure, that the interpreter doesn't try to
176 // delete it a second time.
177 //
178 SetBit(kCanDelete);
179 gInterpreter->DeleteGlobal(this);
180
181 fNumUsers = 2;
182
183 Draw();
184}
185
186// ------------------------------------------------------------------------
187//
188// default constructor
189//
190MagicReversi::MagicReversi()
191 : fGeomCam(NULL), fDone(NULL)
192{
193 SetNewCamera(new MGeomCamMagic);
194
195 Init();
196}
197
198MagicReversi::MagicReversi(const MGeomCam &geom)
199 : fGeomCam(NULL), fDone(NULL)
200{
201 SetNewCamera(static_cast<MGeomCam*>(geom.Clone()));
202
203 Init();
204}
205
206// ------------------------------------------------------------------------
207//
208// Destructor. Deletes TClonesArrays for hexagons and legend elements.
209//
210MagicReversi::~MagicReversi()
211{
212 Free();
213
214 for (int i=0; i<6; i++)
215 delete fUsrTxt[i];
216
217 if (fDone)
218 delete fDone;
219}
220
221// ------------------------------------------------------------------------
222//
223// This is called at any time the canvas should get repainted.
224// Here we maintain an aspect ratio of 5/4=1.15. This makes sure,
225// that the camera image doesn't get distorted by resizing the canvas.
226//
227void MagicReversi::Paint(Option_t *opt)
228{
229 const Float_t r = fGeomCam->GetMaxRadius();
230
231 MH::SetPadRange(-r, -r, r, r*1.1);
232
233 TAttLine line;
234 TAttFill fill;
235
236 // FIXME:
237 for (UInt_t i=0; i<fNumPixels; i++)
238 {
239 const MGeom &pix = (*fGeomCam)[i];
240
241 fill.SetFillColor(fColors[i]);
242 pix.PaintPrimitive(line, fill);
243
244 //
245 // Adopt absolute sized of markers to relative range
246 //
247 Float_t r = (*fGeomCam)[i].GetT()*gPad->XtoAbsPixel(1)/325;
248 GetFlag(i)->SetMarkerSize(20.0*r/fRange);
249
250 if (pix.TestBit(kHasFlag))
251 GetFlag(i)->Paint();
252
253 GetText(i)->Paint();
254 }
255}
256
257// ------------------------------------------------------------------------
258//
259// Call this function to draw the camera layout into your canvas.
260// Setup a drawing canvas. Add this object and all child objects
261// (hexagons, etc) to the current pad. If no pad exists a new one is
262// created.
263//
264void MagicReversi::Draw(Option_t *option)
265{
266 //
267 // if no canvas is yet existing to draw into, create a new one
268 //
269 if (!gPad)
270 new TCanvas("MagicReversi", "Magic Reversi", 0, 0, 800, 800);
271
272 gPad->SetBorderMode(0);
273
274 //
275 // Append this object, so that the aspect ratio is maintained
276 // (Paint-function is called)
277 //
278 AppendPad(option);
279
280 //
281 // Draw the title text
282 //
283 for (int i=0; i<6; i++)
284 {
285 fUsrTxt[i] = new TText;
286 fUsrTxt[i]->SetTextAlign(13); // left/bottom
287 fUsrTxt[i]->SetTextSize(0.03);
288 fUsrTxt[i]->SetTextColor(kRed+i);
289#if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06)
290 fUsrTxt[i]->SetBit(kNoContextMenu|kCannotPick);
291#endif
292 fUsrTxt[i]->Draw();
293 }
294
295 //
296 // Reset the game pad
297 //
298 Reset();
299}
300
301void MagicReversi::Update()
302{
303 int i;
304 for (i=0; i<fNumUsers; i++)
305 {
306 TString txt = "Pixels: ";
307 txt += fUsrPts[i];
308
309 if (fNumUser==i)
310 txt += " <*>";
311
312 fUsrTxt[i]->SetText(-fRange*0.95, fRange-(i+1)*fRange*0.06, txt);
313 }
314 for (; i<6; i++)
315 fUsrTxt[i]->SetText(0, 0, "");
316}
317
318void MagicReversi::TwoPlayer()
319{
320 fNumUsers = 2;
321 Reset();
322}
323
324void MagicReversi::ThreePlayer()
325{
326 fNumUsers = 3;
327 Reset();
328}
329
330void MagicReversi::FourPlayer()
331{
332 fNumUsers = 4;
333 Reset();
334}
335
336void MagicReversi::FivePlayer()
337{
338 fNumUsers = 5;
339 Reset();
340}
341
342void MagicReversi::SixPlayer()
343{
344 fNumUsers = 6;
345 Reset();
346}
347
348// ------------------------------------------------------------------------
349//
350// reset the all pixel colors to a default value
351//
352void MagicReversi::Reset()
353{
354 if (fDone)
355 {
356 delete fDone;
357 fDone = NULL;
358 }
359
360 for (UInt_t i=0; i<fNumPixels; i++)
361 {
362 fColors[i] = kEmpty;
363 (*fGeomCam)[i].ResetBit(kUserBits);
364
365 GetFlag(i)->SetMarkerColor(kBlack);
366 GetText(i)->SetText(0, 0, "");
367 }
368
369 fNumUser = 0;
370
371 for (int i=0; i<6; i++)
372 fUsrPts[i]=0;
373
374 for (int i=1; i<5*fNumUsers; i++)
375 {
376 fColors[i-1] = i%fNumUsers+kRed;
377 fUsrPts[i%fNumUsers]++;
378 }
379
380 Update();
381
382 gPad->SetFillColor(22);
383
384#if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06)
385 SetBit(kNoContextMenu);
386#endif
387}
388
389void MagicReversi::Done()
390{
391 Int_t max = 0;
392 Int_t winner = 0;
393
394 for (int i=0; i<6; i++)
395 if (fUsrPts[i]>max)
396 {
397 winner = i;
398 max = fUsrPts[i];
399 }
400
401 TString txt = "Player #";
402 txt += winner+1;
403 txt += " wins (";
404 txt += max;
405 txt += ")";
406
407 fDone = new TText(0, 0, txt);
408 fDone->SetTextColor(kWhite);
409 fDone->SetTextAlign(22);
410 fDone->SetTextSize(0.05);
411#if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06)
412 fDone->SetBit(kNoContextMenu|kCannotPick);
413#endif
414 fDone->Draw();
415
416 gPad->SetFillColor(winner+kRed);
417
418#if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06)
419 ResetBit(kNoContextMenu);
420#endif
421}
422
423Bool_t MagicReversi::Flip(Int_t origidx, Bool_t flip)
424{
425 const Int_t col = kRed+fNumUser;
426
427 int test[6] = {0,0,0,0,0,0};
428
429 for (int dir=MGeomPix::kRightTop; dir<=MGeomPix::kLeftTop; dir++)
430 {
431 Int_t idx = origidx;
432 Int_t length = 0;
433
434 while (1)
435 {
436 idx = fGeomCam->GetNeighbor(idx, dir);
437 if (idx<0 || fColors[idx]==kEmpty)
438 break;
439
440 if (fColors[idx]==col)
441 {
442 if (length!=0)
443 test[dir] = length;
444 break;
445 }
446
447 length++;
448 }
449 }
450
451 int cnt = 0;
452
453 for (int dir=MGeomPix::kRightTop; dir<=MGeomPix::kLeftTop; dir++)
454 {
455 Int_t idx = origidx;
456
457 if (test[dir])
458 cnt++;
459
460 if (flip)
461 for (int i=0; i<test[dir]; i++)
462 {
463 idx = fGeomCam->GetNeighbor(idx, dir);
464
465 fUsrPts[fColors[idx]-kRed]--;
466 fUsrPts[fNumUser]++;
467
468 fColors[idx] = col;
469 }
470 }
471
472 return cnt ? kTRUE : kFALSE;
473}
474
475Bool_t MagicReversi::CheckMoves()
476{
477 for (unsigned int i=0; i<fNumPixels; i++)
478 if (fColors[i]==kEmpty && Flip(i, kFALSE))
479 return kTRUE;
480 return kFALSE;
481}
482
483// ------------------------------------------------------------------------
484//
485// Execute a mouse event on the camera
486//
487void MagicReversi::ExecuteEvent(Int_t event, Int_t px, Int_t py)
488{
489 if (event==kMouseMotion || event==kMouseEnter || event==kMouseLeave ||
490 event==kButton1Up || event==kButton2Up || event==kButton3Up ||
491 event==kButton1Motion || event==kButton2Motion || event==kButton3Motion ||
492 event==kButton2Double || event==kButton3Double ||
493 fDone)
494 return;
495
496 if (event==kKeyPress && py==kKey_Escape)
497 {
498 Done();
499 gPad->Modified();
500 gPad->Update();
501 return;
502 }
503
504 UInt_t idx;
505 for (idx=0; idx<fNumPixels; idx++)
506 if ((*fGeomCam)[idx].DistancetoPrimitive(px, py)<=0)
507 break;
508
509 if (idx==fNumPixels)
510 return;
511
512 if (event==kButton1Down && fColors[idx]==kEmpty)
513 {
514 if (!Flip(idx, kTRUE))
515 return;
516
517 fUsrPts[fNumUser]++;
518
519 fColors[idx] = kRed+fNumUser;
520
521 Int_t start = fNumUser;
522
523 fNumUser++;
524 fNumUser%=fNumUsers;
525
526 while (!CheckMoves())
527 {
528 cout << "Sorry, no moves possible for player #" << fNumUser << endl;
529 fNumUser++;
530 fNumUser%=fNumUsers;
531
532 if (fNumUser==start)
533 {
534 Done();
535 break;
536 }
537 }
538
539 Update();
540 }
541
542 gPad->Modified();
543}
Note: See TracBrowser for help on using the repository browser.