Index: trunk/MagicSoft/Mars/mtools/MagicReversi.cc
===================================================================
--- trunk/MagicSoft/Mars/mtools/MagicReversi.cc	(revision 1880)
+++ trunk/MagicSoft/Mars/mtools/MagicReversi.cc	(revision 1880)
@@ -0,0 +1,630 @@
+/* ======================================================================== *\
+!
+! *
+! * This file is part of MARS, the MAGIC Analysis and Reconstruction
+! * Software. It is distributed to you in the hope that it can be a useful
+! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
+! * It is distributed WITHOUT ANY WARRANTY.
+! *
+! * Permission to use, copy, modify and distribute this software and its
+! * documentation for any purpose is hereby granted without fee,
+! * provided that the above copyright notice appear in all copies and
+! * that both that copyright notice and this permission notice appear
+! * in supporting documentation. It is provided "as is" without express
+! * or implied warranty.
+! *
+!
+!
+!   Author(s): Thomas Bretz 03/2003 <mailto:tbretz@astro.uni-wuerzburg.de>
+!
+!   Copyright: MAGIC Software Development, 2000-2003
+!
+!
+\* ======================================================================== */
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// MagicReversi
+// ------------
+//
+// Camera Display Games: Reversi
+//
+// Start the game by:
+//   MagicReversi reversi;
+//
+////////////////////////////////////////////////////////////////////////////
+#include "MagicReversi.h"
+
+#include <iostream.h>
+
+#include <TText.h>
+#include <TMarker.h>
+#include <TRandom.h>
+#include <TCanvas.h>
+#include <TClonesArray.h>
+#include <TInterpreter.h>
+
+#include "MHexagon.h"
+
+#include "MGeomPix.h"
+#include "MGeomCamCT1.h"
+#include "MGeomCamMagic.h"
+
+ClassImp(MagicReversi);
+/*
+const Int_t MagicReversi::fColorBombs[7] = {
+    22,
+    kYellow,
+    kGreen,
+    kBlue,
+    kCyan,
+    kMagenta,
+    kRed
+};
+*/
+void MagicReversi::Free()
+{
+    if (!fGeomCam)
+        return;
+
+    fPixels->Delete();
+    fText->Delete();
+    fFlags->Delete();
+
+    delete fText;
+    delete fFlags;
+    delete fPixels;
+
+    delete fGeomCam;
+}
+
+void MagicReversi::ChangeCamera()
+{
+    static Bool_t ct1=kFALSE;
+
+    cout << "Change to " << (ct1?"Magic":"CT1") << endl;
+
+    if (ct1)
+        SetNewCamera(new MGeomCamMagic);
+    else
+        SetNewCamera(new MGeomCamCT1);
+
+    ct1 = !ct1;
+
+    Reset();
+    DrawHexagons();
+}
+
+void MagicReversi::SetNewCamera(MGeomCam *geom)
+{
+    Free();
+
+    //
+    //  Reset the display geometry
+    //
+    fW=0;
+    fH=0;
+
+    //
+    //  Set new camera
+    //
+    fGeomCam = geom;
+
+    //
+    //  create the hexagons of the display
+    //
+    fNumPixels = fGeomCam->GetNumPixels();
+    fRange     = fGeomCam->GetMaxRadius();
+
+    //
+    // Construct all hexagons. Use new-operator with placement
+    //
+//    fNumBombs = fNumPixels/5;
+
+    fText   = new TClonesArray("TText",    fNumPixels);
+    fFlags  = new TClonesArray("TMarker",  fNumPixels);
+    fPixels = new TClonesArray("MHexagon", fNumPixels);
+
+    for (UInt_t i=0; i<fNumPixels; i++)
+    {
+        MHexagon &h = *new ((*fPixels)[i]) MHexagon((*fGeomCam)[i]);
+#if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06)
+        h.SetBit(kNoContextMenu|kCannotPick);
+#endif
+
+        TText &t = *new ((*fText)[i]) TText;
+        t.SetTextFont(122);
+        t.SetTextAlign(22);   // centered/centered
+        t.SetTextSize(0.3*h.GetD()/fRange);
+#if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06)
+        t.SetBit(kNoContextMenu|kCannotPick);
+#endif
+
+        const MGeomPix &pix = (*fGeomCam)[i];
+
+        TMarker &m = *new ((*fFlags)[i]) TMarker(pix.GetX(), pix.GetY(), kOpenStar);
+#if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06)
+        m.SetBit(kNoContextMenu|kCannotPick);
+#endif
+    }
+}
+
+// ------------------------------------------------------------------------
+//
+// Draw all pixels of the camera
+//  (means apend all pixelobjects to the current pad)
+//
+void MagicReversi::DrawHexagons()
+{
+    for (UInt_t i=0; i<fNumPixels; i++)
+        (*this)[i].Draw();
+}
+
+// ------------------------------------------------------------------------
+//
+//  default constructor
+//
+MagicReversi::MagicReversi()
+    : fGeomCam(NULL), fDone(NULL), fW(0), fH(0), fDrawingPad(NULL), fIsAllocated(kFALSE)
+{
+    SetNewCamera(new MGeomCamCT1);
+
+    //
+    // Make sure, that the object is destroyed when the canvas/pad is
+    // destroyed. Make also sure, that the interpreter doesn't try to
+    // delete it a second time.
+    //
+    SetBit(kCanDelete);
+    gInterpreter->DeleteGlobal(this);
+
+    Draw();
+}
+
+// ------------------------------------------------------------------------
+//
+// Destructor. Deletes TClonesArrays for hexagons and legend elements.
+//
+MagicReversi::~MagicReversi()
+{
+    Free();
+
+    for (int i=0; i<6; i++)
+        delete fUsrTxt[i];
+
+    if (fDone)
+        delete fDone;
+
+    if (fDrawingPad->GetListOfPrimitives()->FindObject(this)==this)
+    {
+        fDrawingPad->RecursiveRemove(this);
+        delete fDrawingPad;
+    }
+}
+
+// ------------------------------------------------------------------------
+//
+// This is called at any time the canvas should get repainted.
+// Here we maintain an aspect ratio of 5/4=1.15. This makes sure,
+// that the camera image doesn't get distorted by resizing the canvas.
+//
+void MagicReversi::Paint(Option_t *opt)
+{
+    const UInt_t w = (UInt_t)(gPad->GetWw()*gPad->GetAbsWNDC());
+    const UInt_t h = (UInt_t)(gPad->GetWh()*gPad->GetAbsHNDC());
+
+    //
+    // Check for a change in width or height, and make sure, that the
+    // first call also sets the range
+    //
+    if (w*fH == h*fW && fW && fH)
+        return;
+
+    //
+    // Calculate aspect ratio (5/4=1.25 recommended)
+    //
+    const Double_t ratio = (Double_t)w/h;
+
+    Float_t x;
+    Float_t y;
+
+    if (ratio>1.0)
+    {
+        x = fRange*(ratio*2-1);
+        y = fRange;
+    }
+    else
+    {
+        x = fRange;
+        y = fRange/ratio;
+    }
+
+    fH = h;
+    fW = w;
+
+    //
+    // Set new range
+    //
+    fDrawingPad->Range(-fRange, -y, x, y);
+
+    //
+    // Adopt absolute sized of markers to relative range
+    //
+    for (UInt_t i=0; i<fNumPixels; i++)
+    {
+        Float_t r = (*this)[i].GetD()*gPad->XtoAbsPixel(1)/325;
+        GetFlag(i)->SetMarkerSize(20.0*r/fRange);
+    }
+}
+
+// ------------------------------------------------------------------------
+//
+// Call this function to draw the camera layout into your canvas.
+// Setup a drawing canvas. Add this object and all child objects
+// (hexagons, etc) to the current pad. If no pad exists a new one is
+// created.
+//
+void MagicReversi::Draw(Option_t *option)
+{
+    // root 3.02:
+    // gPad->SetFixedAspectRatio()
+
+    if (fDrawingPad)
+        return;
+
+    //
+    // if no canvas is yet existing to draw into, create a new one
+    //
+    if (!gPad)
+    {
+        /*TCanvas *c =*/ new TCanvas("MagicReversi", "Magic Reversi", 0, 0, 800, 800);
+        //c->ToggleEventStatus();
+        fIsAllocated = kTRUE;
+    }
+    else
+        fIsAllocated = kFALSE;
+
+    fDrawingPad = gPad;
+    fDrawingPad->SetBorderMode(0);
+
+    //
+    // Append this object, so that the aspect ratio is maintained
+    // (Paint-function is called)
+    //
+    AppendPad(option);
+
+    //
+    // Draw the title text
+    //
+    for (int i=0; i<6; i++)
+    {
+        fUsrTxt[i] = new TText;
+        fUsrTxt[i]->SetTextAlign(13);       // left/bottom
+        fUsrTxt[i]->SetTextSize(0.03);
+        fUsrTxt[i]->SetTextColor(kRed+i);  
+#if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06)
+        fUsrTxt[i]->SetBit(kNoContextMenu|kCannotPick);
+#endif
+        fUsrTxt[i]->Draw();
+    }
+
+    //
+    // Reset the game pad
+    //
+    Reset();
+    DrawHexagons();
+}
+
+void MagicReversi::Update()
+{
+    for (int i=0; i<fNumUsers; i++)
+    {
+        TString txt = "Pixels: ";
+        txt += fUsrPts[i];
+
+        if (fNumUser==i)
+            txt += " <*>";
+
+        fUsrTxt[i]->SetText(-fRange*0.95, fRange-(i+1)*fRange*0.06, txt);
+    }
+}
+
+// ------------------------------------------------------------------------
+//
+// reset the all pixel colors to a default value
+//
+void MagicReversi::Reset()
+{
+    if (fDone)
+    {
+        delete fDone;
+        fDone = NULL;
+    }
+
+    for (UInt_t i=0; i<fNumPixels; i++)
+    {
+        Remove(GetText(i));
+        Remove(GetFlag(i));
+
+        (*this)[i].SetFillColor(kEmpty);
+        (*fGeomCam)[i].ResetBit(kUserBits);
+
+        GetFlag(i)->SetMarkerColor(kBlack);
+    }
+
+    fNumUsers = 2; // not more than 6!
+    fNumUser  = 0;
+
+    for (int i=0; i<6; i++)
+        fUsrPts[i]=0;
+
+    for (int i=1; i<5*fNumUsers; i++)
+    {
+        (*this)[i-1].SetFillColor(i%fNumUsers+kRed);
+        fUsrPts[i%fNumUsers]++;
+    }
+
+    Update();
+
+    fDrawingPad->SetFillColor(22);
+
+#if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06)
+    fDrawingPad->SetBit(kNoContextMenu);
+    SetBit(kNoContextMenu);
+#endif
+}
+
+void MagicReversi::Done()
+{
+    Int_t max = 0;
+    Int_t winner = 0;
+
+    for (int i=0; i<6; i++)
+        if (fUsrPts[i]>max)
+        {
+            winner = i;
+            max = fUsrPts[i];
+        }
+
+    TString txt = "Player #";
+    txt += winner;
+    txt += " wins (";
+    txt += max;
+    txt += ")";
+
+    fDone = new TText(0, 0, txt);
+    fDone->SetTextColor(kWhite);
+    fDone->SetTextAlign(22);  
+    fDone->SetTextSize(0.05); 
+#if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06)
+    fDone->SetBit(kNoContextMenu|kCannotPick);
+#endif
+    fDone->Draw();
+
+    fDrawingPad->SetFillColor(winner+kRed);
+
+#if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06)
+    fDrawingPad->ResetBit(kNoContextMenu);
+    ResetBit(kNoContextMenu);
+#endif
+}
+
+void MagicReversi::Remove(TObject *obj)
+{
+    fDrawingPad->RecursiveRemove(obj);
+}
+
+Int_t MagicReversi::GetDirection(Int_t src, Int_t dst) const
+{
+    const MGeomPix &pix1=(*fGeomCam)[dst];
+    const MGeomPix &pix2=(*fGeomCam)[src];
+
+    const Double_t x1 = pix1.GetX();
+    const Double_t y1 = pix1.GetY();
+
+    const Double_t x2 = pix2.GetX();
+    const Double_t y2 = pix2.GetY();
+
+    if (x1>=x2 && y1>y2) return kRightTop;
+    if (x1>=x2 && y1<y2) return kRightBottom;
+    if (x1<=x2 && y1>y2) return kLeftTop;
+    if (x1<=x2 && y1<y2) return kLeftBottom;
+    if (x1>x2)           return kRight;
+    if (x1<x2)           return kLeft;
+
+    return -1;
+}
+
+Int_t MagicReversi::GetNeighbor(Int_t idx, Int_t dir) const
+{
+    MGeomPix &pix=(*fGeomCam)[idx];
+
+    //
+    // search for the neighbor in the given direction
+    //
+    int i;
+    for (i=0; i<pix.GetNumNeighbors(); i++)
+        if (GetDirection(idx, pix.GetNeighbor(i))==dir)
+            return pix.GetNeighbor(i);
+
+    return -1;
+}
+
+Bool_t MagicReversi::Flip(Int_t origidx, Bool_t flip)
+{
+    const Int_t col = kRed+fNumUser;
+
+    int test[6] = {0,0,0,0,0,0};
+
+    for (int dir=kRightTop; dir<=kLeftTop; dir++)
+    {
+        Int_t idx = origidx;
+        Int_t length = 0;
+
+        while (1)
+        {
+            idx = GetNeighbor(idx, dir);
+            if (idx<0 || (*this)[idx].GetFillColor()==kEmpty)
+                break;
+
+            if ((*this)[idx].GetFillColor()==col)
+            {
+                if (length!=0)
+                    test[dir] = length;
+                break;
+            }
+
+            length++;
+        }
+    }
+
+    int cnt = 0;
+
+    for (int dir=kRightTop; dir<=kLeftTop; dir++)
+    {
+        Int_t idx = origidx;
+
+        if (test[dir])
+            cnt++;
+
+        if (flip)
+            for (int i=0; i<test[dir]; i++)
+            {
+                idx = GetNeighbor(idx, dir);
+
+                fUsrPts[(*this)[idx].GetFillColor()-kRed]--;
+                fUsrPts[fNumUser]++;
+
+                (*this)[idx].SetFillColor(col);
+            }
+    }
+
+    return cnt ? kTRUE : kFALSE;
+}
+
+Bool_t MagicReversi::CheckMoves()
+{
+    for (unsigned int i=0; i<fNumPixels; i++)
+        if ((*this)[i].GetFillColor()==kEmpty && Flip(i, kFALSE))
+            return kTRUE;
+    return kFALSE;
+}
+
+// ------------------------------------------------------------------------
+//
+// Execute a mouse event on the camera
+//
+void MagicReversi::ExecuteEvent(Int_t event, Int_t px, Int_t py)
+{
+    if (event==kMouseMotion   || event==kMouseEnter    || event==kMouseLeave    ||
+        event==kButton1Up     || event==kButton2Up     || event==kButton3Up     ||
+        event==kButton1Motion || event==kButton2Motion || event==kButton3Motion ||
+                                 event==kButton2Double || event==kButton3Double ||
+        fDone)
+        return;
+
+    UInt_t idx;
+    for (idx=0; idx<fNumPixels; idx++)
+        if ((*fPixels)[idx]->DistancetoPrimitive(px, py)==0)
+            break;
+
+    if (idx==fNumPixels)
+        return;
+
+    if (event==kButton1Down && (*this)[idx].GetFillColor()==kEmpty)
+    {
+        if (!Flip(idx, kTRUE))
+            return;
+
+        fUsrPts[fNumUser]++;
+
+        (*this)[idx].SetFillColor(kRed+fNumUser);
+
+        Int_t start = fNumUser;
+
+        fNumUser++;
+        fNumUser%=fNumUsers;
+
+        while (!CheckMoves())
+        {
+            cout << "Sorry, no moves possible!" << endl;
+            fNumUser++;
+            fNumUser%=fNumUsers;
+
+            if (fNumUser==start)
+                Done();
+        }
+
+        Update();
+    }
+
+    fDrawingPad->Modified();
+
+    /*
+    if (event==kKeyPress && py==0x1000)
+    {
+        Reset();
+        return;
+    }
+    */
+    /*
+    UInt_t idx;
+    for (idx=0; idx<fNumPixels; idx++)
+        if ((*fPixels)[idx]->DistancetoPrimitive(px, py)==0)
+            break;
+
+    if (idx==fNumPixels)
+        return;
+
+    MGeomPix &pix=(*fGeomCam)[idx];
+
+    if (event==kButton1Double)
+    {
+        OpenHexagon(idx);
+
+        if (pix.TestBit(kHasBomb))
+            Done("Argh... you hit the Bomb!!!", kRed);
+    }
+
+    if (event==kButton1Down && !pix.TestBit(kIsVisible))
+    {
+        if (pix.TestBit(kHasFlag))
+            Remove(GetFlag(idx));
+        else
+            GetFlag(idx)->Draw();
+
+        pix.InvertBit(kHasFlag);
+    }
+
+    UInt_t vis=fNumBombs;
+    UInt_t flg=fNumBombs;
+    for (UInt_t i=0; i<fNumPixels; i++)
+    {
+        if ((*fGeomCam)[i].TestBit(kIsVisible))
+            vis++;
+        if ((*fGeomCam)[i].TestBit(kHasFlag))
+            flg--;
+    }
+
+    Update(flg);
+
+    if (vis==fNumPixels && !fDone)
+        Done("Great! Congratulations, you did it!", kGreen);
+
+    fDrawingPad->Modified();
+      */
+    /*
+     switch (event)
+     {
+     case kNoEvent:       cout << "No Event" << endl; break;
+     case kButton1Down:   cout << "Button 1 down" << endl; break;
+     case kButton2Down:   cout << "Button 2 down" << endl; break;
+     case kButton3Down:   cout << "Button 3 down" << endl; break;
+     case kKeyDown:       cout << "Key down" << endl; break;
+     case kKeyUp:         cout << "Key up" << endl; break;
+     case kKeyPress:      cout << "Key press" << endl; break;
+     case kButton1Locate: cout << "Button 1 locate" << endl; break;
+     case kButton2Locate: cout << "Button 2 locate" << endl; break;
+     case kButton3Locate: cout << "Button 3 locate" << endl; break;
+    }
+    */
+}
Index: trunk/MagicSoft/Mars/mtools/MagicReversi.h
===================================================================
--- trunk/MagicSoft/Mars/mtools/MagicReversi.h	(revision 1880)
+++ trunk/MagicSoft/Mars/mtools/MagicReversi.h	(revision 1880)
@@ -0,0 +1,93 @@
+#ifndef MARS_MagicReversi
+#define MARS_MagicReversi
+
+#ifndef MARS_MAGIC
+#include "MAGIC.h"
+#endif
+#ifndef ROOT_TClonesArray
+#include <TClonesArray.h>
+#endif
+
+class TText;
+class TMarker;
+class TVirtualPad;
+
+class MGeomCam;
+class MHexagon;
+
+class MagicReversi : public TObject
+{
+private:
+    enum {
+        kRightTop,
+        kRight,
+        kRightBottom,
+        kLeftBottom,
+        kLeft,
+        kLeftTop
+    };
+//    static const Int_t fColorBombs[7]; // colors for the hexagons
+
+    MGeomCam      *fGeomCam;       // pointer to camera geometry
+
+    UInt_t         fNumPixels;     // number of pixels in the present geometry
+    Float_t        fRange;         // the range in millimeters of the present geometry
+
+    TClonesArray  *fPixels;        // array of all hexagons
+    TClonesArray  *fText;          // array of all texts
+    TClonesArray  *fFlags;         // array of all texts
+
+    TText         *fDone;          // TText showing the 'Game over'
+    TText         *fUsrTxt[6];     // TText showing the numbers of pixels and bombs
+
+    UInt_t         fW;             // Width of canvas
+    UInt_t         fH;             // Height of canvas
+    TVirtualPad   *fDrawingPad;    // pad in which we are drawing
+    Bool_t         fIsAllocated;
+
+    Int_t          fNumUsers;
+    Int_t          fNumUser;
+    Int_t          fUsrPts[6];
+
+    enum
+    {
+        kEmpty     = 50,
+        kIsVisible = BIT(16),
+        kHasBomb   = BIT(17),
+        kHasFlag   = BIT(18),
+        kUserBits  = 0x7fc000 // 14-23 are allowed
+    };
+
+    MHexagon &operator[](int i) { return *((MHexagon*)fPixels->At(i)); }
+
+    TText   *GetText(Int_t i) { return (TText*)fText->At(i); }
+    TMarker *GetFlag(Int_t i) { return (TMarker*)fFlags->At(i); }
+
+    void  Remove(TObject *);
+    void  Done();
+    void  Update();
+    void  SetNewCamera(MGeomCam *);
+    void  DrawHexagons();
+    void  Free();
+
+    Bool_t Flip(Int_t idx, Bool_t flip);
+    Int_t  GetDirection(Int_t src, Int_t dst) const;
+    Int_t  GetNeighbor(Int_t idx, Int_t dir) const;
+    Bool_t CheckMoves();
+
+    void  Paint(Option_t *option="");
+    void  Draw(Option_t *option="");
+    void  ExecuteEvent(Int_t event, Int_t px, Int_t py);
+    Int_t DistancetoPrimitive(Int_t px, Int_t py) { return 0; }
+
+public:
+    MagicReversi();
+    ~MagicReversi();
+
+    void Reset();        //*MENU*
+    void ChangeCamera(); //*MENU*
+
+    ClassDef(MagicReversi, 0) // Magic Camera Games
+};
+
+#endif
Index: trunk/MagicSoft/Mars/mtools/Makefile
===================================================================
--- trunk/MagicSoft/Mars/mtools/Makefile	(revision 1845)
+++ trunk/MagicSoft/Mars/mtools/Makefile	(revision 1880)
@@ -29,4 +29,5 @@
 
 SRCFILES = MChisqEval.cc \
+	   MagicReversi.cc \
 	   MagicSnake.cc \
            MagicShow.cc \
Index: trunk/MagicSoft/Mars/mtools/ToolsLinkDef.h
===================================================================
--- trunk/MagicSoft/Mars/mtools/ToolsLinkDef.h	(revision 1845)
+++ trunk/MagicSoft/Mars/mtools/ToolsLinkDef.h	(revision 1880)
@@ -7,5 +7,5 @@
 #pragma link C++ class MChisqEval+;
 #pragma link C++ class MineSweeper+;
-// #pragma link C++ class MagicReversi+;
+#pragma link C++ class MagicReversi+;
 #pragma link C++ class MagicSnake+;
 #pragma link C++ class MagicShow+;
