RCS file: /sources/gnugo/gnugo/engine/clock.c,v
retrieving revision 1.26
diff -u -r1.26 clock.c
|
|
|
|
| 68 | 68 | }; |
| 69 | 69 | |
| 70 | 70 | struct timer_data { |
| 71 | | struct remaining_time_data official; |
| 72 | | struct remaining_time_data estimated; |
| | 71 | struct remaining_time_data official; // time received from external source |
| | 72 | struct remaining_time_data estimated; // time counted by GnuGO |
| 73 | 73 | int time_out; |
| 74 | 74 | }; |
| 75 | 75 | |
| … |
… |
|
| 127 | 127 | * |
| 128 | 128 | * byo_time > 0 and byo_stones == 0 means no time settings. |
| 129 | 129 | */ |
| 130 | | void |
| | 130 | inline void |
| 131 | 131 | clock_settings(int time, int byo_time, int byo_stones) |
| 132 | 132 | { |
| 133 | 133 | if (time >= 0) |
| … |
… |
|
| 142 | 142 | /* Get time settings. Returns 1 if any time settings have been made, |
| 143 | 143 | * 0 otherwise. |
| 144 | 144 | */ |
| 145 | | int |
| | 145 | inline int |
| 146 | 146 | have_time_settings(void) |
| 147 | 147 | { |
| 148 | 148 | /* According to the semantics of the GTP command 'time_settings', the |
| … |
… |
|
| 220 | 220 | static int last_movenum = -1; |
| 221 | 221 | struct timer_data* const td |
| 222 | 222 | = (color == BLACK) ? &black_time_data : &white_time_data; |
| 223 | | double now = gg_gettimeofday(); |
| | 223 | double now; |
| 224 | 224 | |
| 225 | 225 | if (!have_time_settings()) |
| 226 | 226 | return; |
| 227 | 227 | |
| | 228 | now = gg_gettimeofday(); |
| | 229 | |
| 228 | 230 | if (last_movenum >= 0 |
| 229 | | && movenum == last_movenum + 1 |
| 230 | | && movenum > td->estimated.movenum) { |
| | 231 | && movenum == last_movenum + 1) { |
| 231 | 232 | double time_used = now - last_time; |
| 232 | 233 | td->estimated.time_left -= time_used; |
| 233 | 234 | td->estimated.movenum = movenum; |
| 234 | 235 | td->estimated.time_for_last_move = time_used; |
| 235 | 236 | if (td->estimated.time_left < 0) { |
| 236 | 237 | if (td->estimated.in_byoyomi || byoyomi_stones == 0) { |
| | 238 | |
| | 239 | #ifndef GG_TURN_OFF_DEBUGS |
| 237 | 240 | DEBUG(DEBUG_TIME, "%s ran out of time.\n", color_to_string(color)); |
| 238 | 241 | if (debug & DEBUG_TIME) |
| 239 | 242 | clock_print(color); |
| | 243 | #endif |
| | 244 | |
| 240 | 245 | td->time_out = 1; |
| 241 | 246 | } |
| 242 | 247 | else { |
| … |
… |
|
| 251 | 256 | } |
| 252 | 257 | else if (td->estimated.stones > 0) { |
| 253 | 258 | gg_assert(td->estimated.in_byoyomi); |
| 254 | | td->estimated.stones = td->estimated.stones - 1; |
| | 259 | --td->estimated.stones; |
| 255 | 260 | if (td->estimated.stones == 0) { |
| 256 | 261 | td->estimated.time_left = byoyomi_time; |
| 257 | 262 | td->estimated.stones = byoyomi_stones; |
| … |
… |
|
| 262 | 267 | last_movenum = movenum; |
| 263 | 268 | last_time = now; |
| 264 | 269 | |
| | 270 | #ifndef GG_TURN_OFF_DEBUGS |
| 265 | 271 | /* Update main timer. */ |
| 266 | 272 | if (debug & DEBUG_TIME) |
| 267 | 273 | clock_print(color); |
| | 274 | #endif |
| 268 | 275 | } |
| 269 | 276 | |
| 270 | 277 | |
| … |
… |
|
| 297 | 304 | |
| 298 | 305 | if (timer->stones == 0) { |
| 299 | 306 | /* Main time running. */ |
| 300 | | *time_left = timer->time_left + byoyomi_time; |
| | 307 | *time_left = timer->time_left; |
| 301 | 308 | if (byoyomi_time > 0) |
| | 309 | { |
| | 310 | *time_left += byoyomi_time; |
| 302 | 311 | *stones_left = byoyomi_stones; |
| | 312 | } |
| 303 | 313 | else { |
| 304 | 314 | /* Absolute time. Here we aim to be able to play at least X more |
| 305 | 315 | * moves or a total of Y moves. We choose Y as a third of the |
| … |
… |
|
| 331 | 341 | adjust_level_offset(int color) |
| 332 | 342 | { |
| 333 | 343 | double time_for_last_move; |
| 334 | | double time_left; |
| 335 | | int stones_left; |
| | 344 | double time_left, estimated_time; |
| | 345 | int stones_left, new_level; |
| 336 | 346 | |
| 337 | 347 | if (!analyze_time_data(color, &time_for_last_move, &time_left, &stones_left)) |
| 338 | 348 | return; |
| … |
… |
|
| 342 | 352 | * |
| 343 | 353 | * FIXME: Use rules with at least some theoretical basis. |
| 344 | 354 | */ |
| 345 | | if (time_left < time_for_last_move * (stones_left + 3)) |
| 346 | | level_offset--; |
| 347 | | if (time_left < time_for_last_move * stones_left) |
| 348 | | level_offset--; |
| 349 | | if (3 * time_left < 2 * time_for_last_move * stones_left) |
| 350 | | level_offset--; |
| 351 | | if (2 * time_left < time_for_last_move * stones_left) |
| 352 | | level_offset--; |
| 353 | | if (3 * time_left < time_for_last_move * stones_left) |
| 354 | | level_offset--; |
| 355 | | |
| 356 | | if (time_for_last_move == 0) |
| 357 | | time_for_last_move = 1; |
| 358 | | if (time_left > time_for_last_move * (stones_left + 6)) |
| 359 | | level_offset++; |
| 360 | | if (time_left > 2 * time_for_last_move * (stones_left + 6)) |
| 361 | | level_offset++; |
| | 355 | if (time_for_last_move < 0.1) |
| | 356 | time_for_last_move = 0.1; |
| 362 | 357 | |
| 363 | | if (level + level_offset < min_level) |
| 364 | | level_offset = min_level - level; |
| | 358 | estimated_time = time_for_last_move * stones_left; |
| | 359 | |
| | 360 | if (time_left < estimated_time) |
| | 361 | { |
| | 362 | --level_offset; |
| | 363 | |
| | 364 | if (1.33 * time_left < estimated_time) |
| | 365 | { |
| | 366 | --level_offset; |
| | 367 | |
| | 368 | if (2 * time_left < estimated_time) |
| | 369 | { |
| | 370 | level_offset -= 2; |
| | 371 | |
| | 372 | if (4 * time_left < estimated_time) |
| | 373 | level_offset -= 2; |
| | 374 | } |
| | 375 | } |
| | 376 | } |
| | 377 | else if (0.8 * time_left > estimated_time) |
| | 378 | { |
| | 379 | ++level_offset; |
| 365 | 380 | |
| 366 | | if (level + level_offset > max_level) |
| | 381 | if (0.5 * time_left > estimated_time) |
| | 382 | level_offset += 2; |
| | 383 | } |
| | 384 | |
| | 385 | new_level = level + level_offset; |
| | 386 | |
| | 387 | if (new_level < min_level) |
| | 388 | level_offset = min_level - level; |
| | 389 | else if (new_level > max_level) |
| 367 | 390 | level_offset = max_level - level; |
| 368 | 391 | |
| 369 | 392 | DEBUG(DEBUG_TIME, "New level %d (%d %C %f %f %d)\n", level + level_offset, |
| … |
… |
|
| 375 | 398 | /* Interface to level settings. */ |
| 376 | 399 | /********************************/ |
| 377 | 400 | |
| 378 | | int |
| | 401 | inline int |
| 379 | 402 | get_level() |
| 380 | 403 | { |
| 381 | 404 | return level + level_offset; |
| 382 | 405 | } |
| 383 | 406 | |
| 384 | | void |
| | 407 | inline void |
| 385 | 408 | set_level(int new_level) |
| 386 | 409 | { |
| 387 | 410 | level = new_level; |
| … |
… |
|
| 392 | 415 | min_level = level; |
| 393 | 416 | } |
| 394 | 417 | |
| 395 | | void |
| | 418 | inline void |
| 396 | 419 | set_max_level(int new_max) |
| 397 | 420 | { |
| 398 | 421 | max_level = new_max; |
| 399 | 422 | } |
| 400 | 423 | |
| 401 | | void |
| | 424 | inline void |
| 402 | 425 | set_min_level(int new_min) |
| 403 | 426 | { |
| 404 | 427 | min_level = new_min; |