00001
00002
00003
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
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