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