Index   Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

SgTimeRecord.cpp

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 /** @file SgTimeRecord.cpp
00003     See SgTimeRecord.h.
00004 */
00005 //----------------------------------------------------------------------------
00006 
00007 #include "SgSystem.h"
00008 #include "SgTimeRecord.h"
00009 
00010 #include <iomanip>
00011 #include <limits>
00012 #include <sstream>
00013 #include "SgDebug.h"
00014 #include "SgNode.h"
00015 #include "SgProp.h"
00016 #include "SgTime.h"
00017 #include "SgWrite.h"
00018 
00019 using namespace std;
00020 
00021 //----------------------------------------------------------------------------
00022 
00023 SgTimeRecord::SgTimeRecord(int numMoves, double period, double overhead,
00024                            bool loseOnTime)
00025     : m_overtimeNumMoves(numMoves),
00026       m_overtimePeriod(period),
00027       m_overhead(overhead),
00028       m_loseOnTime(loseOnTime),
00029       m_player(SG_BLACK),
00030       m_clockIsOn(false),
00031       m_suspended(false),
00032       m_atNode(0),
00033       m_timeLeft(0),
00034       m_movesLeft(0),
00035       m_timeOfLastUpdate(0)
00036 {
00037 }
00038 
00039 SgTimeRecord::SgTimeRecord(bool oneMoveOnly, double timeForMove)
00040     : m_overtimeNumMoves(1),
00041       m_overtimePeriod(timeForMove),
00042       m_overhead(0),
00043       m_loseOnTime(false),
00044       m_player(SG_BLACK),
00045       m_clockIsOn(false),
00046       m_suspended(false),
00047       m_atNode(0),
00048       m_timeLeft(timeForMove),
00049       m_movesLeft(1),
00050       m_timeOfLastUpdate(0)
00051 {
00052     SG_DEBUG_ONLY(oneMoveOnly);
00053     SG_ASSERT(oneMoveOnly);
00054 }
00055 
00056 SgBWArray<double> SgTimeRecord::GetTimeFromTree(SgNode& node)
00057 {
00058     SgBWArray<double> time;
00059     time[SG_BLACK] =
00060         node.TopProp(SG_PROP_TIME_BLACK)->GetRealProp(SG_PROP_TIME_BLACK);
00061     time[SG_WHITE] =
00062         node.TopProp(SG_PROP_TIME_WHITE)->GetRealProp(SG_PROP_TIME_WHITE);
00063     return time;
00064 }
00065 
00066 SgBWArray<int> SgTimeRecord::GetOTMovesFromTree(SgNode& node)
00067 {
00068     SgBWArray<int> numMoves;
00069     numMoves[SG_BLACK] =
00070         node.TopProp(SG_PROP_OT_BLACK)->GetIntProp(SG_PROP_OT_BLACK);
00071     numMoves[SG_WHITE] =
00072         node.TopProp(SG_PROP_OT_WHITE)->GetIntProp(SG_PROP_OT_WHITE);
00073     return numMoves;
00074 }
00075 
00076 SgClockState SgTimeRecord::GetClockState() const
00077 {
00078     if (m_clockIsOn)
00079         return SG_CLOCK_RUNNING;
00080     else if (m_suspended)
00081         return SG_CLOCK_SUSPENDED;
00082     else
00083         return SG_CLOCK_OFF;
00084 }
00085 
00086 double SgTimeRecord::TimeLeft(SgBlackWhite player) const
00087 {
00088     SG_ASSERT_BW(player);
00089     return m_timeLeft[player];
00090 }
00091 
00092 void SgTimeRecord::SetTimeInTree(SgNode& node, SgBWArray<double> time)
00093 {
00094     node.SetRealProp(SG_PROP_TIME_BLACK, time[SG_BLACK]);
00095     node.SetRealProp(SG_PROP_TIME_WHITE, time[SG_WHITE]);
00096 }
00097 
00098 void SgTimeRecord::TurnClockOn(bool turnOn)
00099 {
00100     if (m_suspended || (turnOn != m_clockIsOn))
00101     {
00102         if (turnOn)
00103             m_timeOfLastUpdate = SgTime::Get();
00104         else
00105             UpdateTimeLeft();
00106         m_clockIsOn = turnOn;
00107         m_suspended = false;
00108     }
00109 }
00110 
00111 void SgTimeRecord::SuspendClock()
00112 {
00113     if (m_clockIsOn && ! m_suspended)
00114     {
00115         m_clockIsOn = false;
00116         m_suspended = true;
00117     }
00118 }
00119 
00120 void SgTimeRecord::SetClock(SgNode& node, SgBlackWhite player, double time)
00121 {
00122     node.SetRealProp(SgProp::PlayerProp(SG_PROP_TIME_BLACK, player), time);
00123     m_timeLeft[player] = time;
00124     if (player == m_player)
00125         m_timeOfLastUpdate = SgTime::Get();
00126     if (m_timeLeft[player] <= 0.0001)
00127     {
00128         m_timeLeft[player] = OTPeriod();
00129         m_movesLeft[player] = OTNumMoves();
00130     }
00131 }
00132 
00133 void SgTimeRecord::UpdateTimeLeft()
00134 {
00135     double now = SgTime::Get();
00136     if (m_clockIsOn && (now > m_timeOfLastUpdate))
00137     {
00138         bool outOfTime = (m_timeLeft[m_player] < now - m_timeOfLastUpdate);
00139         m_timeLeft[m_player] -= now - m_timeOfLastUpdate;
00140         if (outOfTime)
00141         {
00142             SgDebug() << "SgTimeRecord: outOfTime\n";
00143             if (UseOvertime() && m_movesLeft[m_player] <= 0)
00144             {
00145                 SgDebug() << "SgTimeRecond: reseting overtime\n";
00146                 m_timeLeft[m_player] += OTPeriod();
00147                 if (m_timeLeft[m_player] > OTPeriod())
00148                     m_timeLeft[m_player] = OTPeriod();
00149                 m_movesLeft[m_player] = OTNumMoves();
00150             }
00151             else if (LoseOnTime())
00152             {
00153                 SgDebug() << "SgTimeRecord: lost on time\n";
00154                 SuspendClock();
00155             }
00156         }
00157     }
00158     m_timeOfLastUpdate = now;
00159 }
00160 
00161 void SgTimeRecord::EnterNode(SgNode& node, SgBlackWhite player)
00162 {
00163     if (m_clockIsOn && &node != m_atNode)
00164         SuspendClock();
00165     m_player = player;
00166     if (! m_clockIsOn)
00167     {
00168         m_atNode = &node;
00169         m_timeLeft = GetTimeFromTree(node);
00170         m_movesLeft = GetOTMovesFromTree(node);
00171         // AR: commented out in Modula-2: fTimeOfLastUpdate := Ticks();
00172     }
00173 }
00174 
00175 void SgTimeRecord::PlayedMove(SgNode& node, SgBlackWhite player)
00176 {
00177     m_atNode = &node;
00178     if (m_suspended && ! node.HasSon())
00179         TurnClockOn(true);
00180     else if (m_clockIsOn)
00181     {
00182         UpdateTimeLeft();
00183         if (UseOvertime())
00184         {
00185             if (m_movesLeft[player] > 0)
00186             {
00187                 m_movesLeft[player]--;
00188                 if (m_movesLeft[player] == 0)
00189                 {
00190                     SgDebug() << "SgTimeRecond: reseting overtime\n";
00191                     m_movesLeft[player] = OTNumMoves();
00192                     m_timeLeft[player] = OTPeriod();
00193                 }
00194             }
00195             node.SetIntProp(SgProp::PlayerProp(SG_PROP_OT_BLACK, player),
00196                             m_movesLeft[player]);
00197         }
00198         m_timeLeft[player] -= Overhead();
00199         node.SetRealProp(SgProp::PlayerProp(SG_PROP_TIME_BLACK, player),
00200                          m_timeLeft[player]);
00201     }
00202 }
00203 
00204 //----------------------------------------------------------------------------
00205 
00206 ostream& operator<<(ostream& out, const SgTimeRecord& time)
00207 {
00208     out << SgWriteLabel("Overhead") << time.Overhead() << '\n'
00209         << SgWriteLabel("UseOvertime") << time.UseOvertime() << '\n'
00210         << SgWriteLabel("OTPeriod") << time.OTPeriod() << '\n'
00211         << SgWriteLabel("OTNumMoves") << time.OTNumMoves() << '\n'
00212         << SgWriteLabel("LoseOnTime") << time.LoseOnTime() << '\n'
00213         << SgWriteLabel("ClockIsRunning") << time.ClockIsRunning() << '\n'
00214         << SgWriteLabel("ClockState") << time.GetClockState() << '\n'
00215         << SgWriteLabel("TimeLeft/B") << time.TimeLeft(SG_BLACK) << '\n'
00216         << SgWriteLabel("TimeLeft/W") << time.TimeLeft(SG_WHITE) << '\n'
00217         << SgWriteLabel("MovesLeft/B") << time.MovesLeft(SG_BLACK) << '\n'
00218         << SgWriteLabel("MovesLeft/W") << time.MovesLeft(SG_WHITE) << '\n';
00219     return out;
00220 }
00221 
00222 ostream& operator<<(ostream& out, SgClockState clockState)
00223 {
00224     switch (clockState)
00225     {
00226     case SG_CLOCK_OFF:
00227         out << "CLOCK_OFF";
00228         break;
00229     case SG_CLOCK_RUNNING:
00230         out << "CLOCK_RUNNING";
00231         break;
00232     case SG_CLOCK_SUSPENDED:
00233         out << "CLOCK_SUSPENDED";
00234         break;
00235     default:
00236         SG_ASSERT(false);
00237         out << "?";
00238     }
00239     return out;
00240 }
00241 
00242 //----------------------------------------------------------------------------
00243 


17 Jun 2010 Doxygen 1.4.7