A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 885 lines 23 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2007-2009 Joshua Simmons <mud at majidejima dot com> 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License 14 * as published by the Free Software Foundation; either version 2 15 * of the License, or (at your option) any later version. 16 * 17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 * KIND, either express or implied. 19 * 20 ****************************************************************************/ 21 22#include "util.h" 23#include "game.h" 24 25 26void metadata_summary (void) 27{ 28 char buffer[256] = ""; 29 30 if (rb->strlen (header.black) || 31 rb->strlen (header.white) || 32 rb->strlen (header.black_rank) || 33 rb->strlen (header.white_rank)) 34 rb->snprintf (buffer, sizeof(buffer), 35 "%s [%s] v. %s [%s] ", 36 header.black, header.black_rank, 37 header.white, header.white_rank); 38 39 if (header.handicap > 1) 40 { 41 rb->snprintf (buffer + rb->strlen(buffer), 42 sizeof (buffer) - rb->strlen (buffer), 43 "%d stones ", header.handicap); 44 } 45 46 if (header.komi != 0 && !(header.komi == 1 && header.handicap > 1)) 47 { 48 snprint_fixed (buffer + rb->strlen(buffer), 49 sizeof (buffer) - rb->strlen (buffer), 50 header.komi); 51 rb->snprintf (buffer + rb->strlen(buffer), 52 sizeof (buffer) - rb->strlen (buffer), 53 " komi "); 54 } 55 56 if (rb->strlen(header.result)) 57 { 58 rb->snprintf (buffer + rb->strlen(buffer), 59 sizeof (buffer) - rb->strlen (buffer), 60 "(%s)", header.result); 61 } 62 63 /* waiting for user input messes up the testing code, so ifdef it*/ 64#if !defined(GBN_TEST) 65 if (rb->strlen(buffer)) 66 { 67 rb->splash(0, buffer); 68 rb->action_userabort(TIMEOUT_BLOCK); 69 } 70#endif 71} 72 73void * 74align_buffer (void *buffer, size_t * buffer_size) 75{ 76 unsigned int wasted = (-(intptr_t) buffer) & 3; 77 78 if (!buffer || !buffer_size) 79 { 80 return NULL; 81 } 82 83 if (*buffer_size <= wasted) 84 { 85 *buffer_size = 0; 86 return NULL; 87 } 88 89 *buffer_size -= wasted; 90 91 return PTR_ADD(buffer, wasted); 92} 93 94 95 96bool 97setup_stack (struct stack_t *stack, void *buffer, size_t buffer_size) 98{ 99 if (!stack || !buffer || !buffer_size) 100 { 101 DEBUGF ("INVALID STACK SETUP!!\n"); 102 return false; 103 } 104 105 buffer = align_buffer (buffer, &buffer_size); 106 107 if (!buffer || !buffer_size) 108 { 109 DEBUGF ("Buffer disappeared after alignment!\n"); 110 return false; 111 } 112 113 stack->buffer = buffer; 114 stack->size = buffer_size; 115 stack->sp = 0; 116 117 return true; 118} 119 120bool 121push_stack (struct stack_t * stack, void *buffer, size_t buffer_size) 122{ 123 if (stack->sp + buffer_size > stack->size) 124 { 125 DEBUGF ("stack full!!\n"); 126 return false; 127 } 128 129 rb->memcpy (&stack->buffer[stack->sp], buffer, buffer_size); 130 131 stack->sp += buffer_size; 132 133 return true; 134} 135 136bool 137pop_stack (struct stack_t * stack, void *buffer, size_t buffer_size) 138{ 139 if (!peek_stack (stack, buffer, buffer_size)) 140 { 141 return false; 142 } 143 144 stack->sp -= buffer_size; 145 146 return true; 147} 148 149bool 150peek_stack (struct stack_t * stack, void *buffer, size_t buffer_size) 151{ 152 if (stack->sp < buffer_size) 153 { 154 return false; 155 } 156 157 rb->memcpy (buffer, &stack->buffer[stack->sp - buffer_size], buffer_size); 158 159 return true; 160} 161 162void 163empty_stack (struct stack_t *stack) 164{ 165 stack->sp = 0; 166} 167 168bool 169push_pos_stack (struct stack_t *stack, unsigned short pos) 170{ 171 return push_stack (stack, &pos, sizeof (pos)); 172} 173 174bool 175push_int_stack (struct stack_t *stack, int num) 176{ 177 return push_stack (stack, &num, sizeof (num)); 178} 179 180bool 181push_char_stack (struct stack_t *stack, char num) 182{ 183 return push_stack (stack, &num, sizeof (num)); 184} 185 186 187 188/* IMPORTANT: keep in sync with the enum prop_type_t enum in types.h */ 189char *prop_names[] = { 190 /* look up the SGF specification for the meaning of these */ 191 "B", "W", 192 "AB", "AW", "AE", 193 194 "PL", "C", 195 196 "DM", "GB", "GW", "HO", "UC", "V", 197 198 "BM", "DO", "IT", "TE", 199 200 "CR", "SQ", "TR", "DD", "MA", "SL", "LB", "N", 201 202 "AP", "CA", "FF", "GM", "ST", "SZ", 203 204 "AN", "PB", "PW", "HA", "KM", "TB", "TW", "BR", "WR", 205 "BT", "WT", "CP", "DT", "EV", "RO", "GN", "GC", "ON", 206 "OT", "PC", "RE", "RU", "SO", "TM", "US", 207 208 "BL", "WL", "OB", "OW", "FG", "PM", "VW" 209}; 210 211/* These seems to be specified by the SGF specification. You can do free 212 form ones as well, but I haven't implemented that (and don't plan to) */ 213const char *ruleset_names[] = { "AGA", "Japanese", "Chinese", "NZ", "GOE" }; 214 215 216 217int 218create_or_open_file (const char *filename) 219{ 220 int fd; 221 222 if (!rb->file_exists (filename)) 223 { 224 fd = rb->creat(filename, 0666); 225 } 226 else 227 { 228 fd = rb->open (filename, O_RDWR); 229 } 230 231 return fd; 232} 233 234 235int 236snprint_fixed (char *buffer, int buffer_size, int fixed) 237{ 238 return rb->snprintf (buffer, buffer_size, "%s%d.%d", 239 fixed < 0 ? "-" : "", 240 abs (fixed) >> 1, 5 * (fixed & 1)); 241} 242 243 244int 245peek_char (int fd) 246{ 247 char peeked_char; 248 249 int result = rb->read (fd, &peeked_char, 1); 250 251 if (result != 1) 252 { 253 return -1; 254 } 255 256 result = rb->lseek (fd, -1, SEEK_CUR); 257 258 if (result < 0) 259 { 260 return -1; 261 } 262 263 return peeked_char; 264} 265 266 267int 268read_char (int fd) 269{ 270 char read_char; 271 272 int result = rb->read (fd, &read_char, 1); 273 274 if (result != 1) 275 { 276 return -1; 277 } 278 279 return read_char; 280} 281 282 283bool 284write_char (int fd, char to_write) 285{ 286 int result = write_file (fd, &to_write, 1); 287 288 if (result != 1) 289 { 290 return false; 291 } 292 293 return true; 294} 295 296ssize_t 297write_file (int fd, const void *buf, size_t count) 298{ 299 const char *buffer = buf; 300 int result; 301 int ret_val = count; 302 303 while (count) 304 { 305 result = rb->write (fd, buffer, count); 306 307 if (result < 0) 308 { 309 return -1; 310 } 311 312 count -= result; 313 buffer += result; 314 } 315 316 return ret_val; 317} 318 319ssize_t 320read_file (int fd, void *buf, size_t count) 321{ 322 char *buffer = buf; 323 int result; 324 int ret_val = count; 325 326 while (count) 327 { 328 result = rb->read (fd, buffer, count); 329 330 if (result <= 0) 331 { 332 return -1; 333 } 334 335 count -= result; 336 buffer += result; 337 } 338 339 return ret_val; 340} 341 342int 343read_char_no_whitespace (int fd) 344{ 345 int result = peek_char_no_whitespace (fd); 346 347 read_char (fd); 348 349 return result; 350} 351 352int 353peek_char_no_whitespace (int fd) 354{ 355 int result; 356 357 while (is_whitespace (result = peek_char (fd))) 358 { 359 read_char (fd); 360 } 361 362 return result; 363} 364 365 366void 367close_file (int *fd) 368{ 369 if (*fd >= 0) 370 { 371 rb->close (*fd); 372 } 373 374 *fd = -1; 375} 376 377bool 378is_whitespace (int value) 379{ 380 if (value == ' ' || 381 value == '\t' || 382 value == '\n' || value == '\r' || value == '\f' || value == '\v') 383 { 384 return true; 385 } 386 else 387 { 388 return false; 389 } 390} 391 392void 393sanitize_string (char *string) 394{ 395 bool escaped = false; 396 397 if (!string) 398 { 399 return; 400 } 401 402 while (1) 403 { 404 switch (*string) 405 { 406 case '\0': 407 return; 408 case '\\': 409 escaped = !escaped; 410 break; 411 case ']': 412 if (!escaped) 413 { 414 *string = ']'; 415 } 416 escaped = false; 417 break; 418 default: 419 break; 420 }; 421 ++string; 422 } 423} 424 425 426bool 427get_header_string_and_size (struct header_t *header, 428 enum prop_type_t type, char **buffer, int *size) 429{ 430 if (buffer == 0 || header == 0) 431 { 432 return false; 433 } 434 435 if (type == PROP_BLACK_NAME) 436 { 437 *buffer = header->black; 438 *size = MAX_NAME; 439 } 440 else if (type == PROP_WHITE_NAME) 441 { 442 *buffer = header->white; 443 *size = MAX_NAME; 444 } 445 else if (type == PROP_BLACK_RANK) 446 { 447 *buffer = header->black_rank; 448 *size = MAX_RANK; 449 } 450 else if (type == PROP_WHITE_RANK) 451 { 452 *buffer = header->white_rank; 453 *size = MAX_RANK; 454 } 455 else if (type == PROP_BLACK_TEAM) 456 { 457 *buffer = header->black_team; 458 *size = MAX_TEAM; 459 } 460 else if (type == PROP_WHITE_TEAM) 461 { 462 *buffer = header->white_team; 463 *size = MAX_TEAM; 464 } 465 else if (type == PROP_DATE) 466 { 467 *buffer = header->date; 468 *size = MAX_DATE; 469 } 470 else if (type == PROP_ROUND) 471 { 472 *buffer = header->round; 473 *size = MAX_ROUND; 474 } 475 else if (type == PROP_EVENT) 476 { 477 *buffer = header->event; 478 *size = MAX_EVENT; 479 } 480 else if (type == PROP_PLACE) 481 { 482 *buffer = header->place; 483 *size = MAX_PLACE; 484 } 485 else if (type == PROP_OVERTIME) 486 { 487 *buffer = header->overtime; 488 *size = MAX_OVERTIME; 489 } 490 else if (type == PROP_RESULT) 491 { 492 *buffer = header->result; 493 *size = MAX_RESULT; 494 } 495 else if (type == PROP_RULESET) 496 { 497 *buffer = header->ruleset; 498 *size = MAX_RULESET; 499 } 500 else 501 { 502 return false; 503 } 504 505 return true; 506} 507 508 509/* TEST CODE BEGINS HERE define GBN_TEST to run this, either in goban.h or 510 in the CFLAGS. The tests will be run when the plugin starts, after 511 which the plugin will exit. Any error stops testing since many tests 512 depend on previous setup. Note: The testing can take a while as there 513 are some big loops. Be patient. */ 514 515#ifdef GBN_TEST 516 517#include "goban.h" 518#include "types.h" 519#include "board.h" 520#include "game.h" 521#include "sgf.h" 522#include "sgf_storage.h" 523 524/* If this isn't on a single line, the line numbers it reports will be wrong. 525 * 526 * I'm sure there's a way to make it better, but it's not really worth it. 527 */ 528#define gbn_assert(test) if (test) {DEBUGF("%d passed\n", __LINE__);} else {DEBUGF("%d FAILED!\n", __LINE__); rb->splashf(10 * HZ, "Test on line %d of util.c failed!", __LINE__); return;} 529 530void 531run_tests (void) 532{ 533 rb->splash (3 * HZ, "Running tests. Failures will stop testing."); 534 535 536 537 /* allocating and freeing storage units */ 538 539 gbn_assert (alloc_storage_sgf ()); 540 541 int prevent_infinite = 100000000; 542 543 int count = 1; 544 while (alloc_storage_sgf () >= 0 && --prevent_infinite) 545 { 546 ++count; 547 } 548 549 gbn_assert (prevent_infinite); 550 gbn_assert (count > 100); 551 552 /* make sure it fails a few times */ 553 gbn_assert (alloc_storage_sgf () < 0); 554 gbn_assert (alloc_storage_sgf () < 0); 555 gbn_assert (alloc_storage_sgf () < 0); 556 557 free_storage_sgf (0); 558 559 gbn_assert (alloc_storage_sgf () == 0); 560 561 gbn_assert (alloc_storage_sgf () < 0); 562 563 int i; 564 for (i = 0; i <= count; ++i) 565 { 566 free_storage_sgf (i); 567 } 568 569 gbn_assert (alloc_storage_sgf () >= 0); 570 --count; 571 572 for (i = 0; i < count; ++i) 573 { 574 gbn_assert (alloc_storage_sgf () >= 0); 575 } 576 577 free_tree_sgf (); 578 579 580 581 /* setting up, saving and loading */ 582 gbn_assert (setup_game (MAX_BOARD_SIZE, MAX_BOARD_SIZE, 0, 15)); 583 gbn_assert (setup_game (MAX_BOARD_SIZE, MAX_BOARD_SIZE, 0, -30)); 584 gbn_assert (setup_game (MAX_BOARD_SIZE, MAX_BOARD_SIZE, 4, 1)); 585 gbn_assert (setup_game (MIN_BOARD_SIZE, MIN_BOARD_SIZE, 1, 1)); 586 587 gbn_assert (setup_game (MIN_BOARD_SIZE, MAX_BOARD_SIZE, 1, 1)); 588 gbn_assert (setup_game (MAX_BOARD_SIZE, MIN_BOARD_SIZE, 1, 1)); 589 590 gbn_assert (!setup_game (MAX_BOARD_SIZE + 1, MAX_BOARD_SIZE + 1, 0, 15)); 591 gbn_assert (!setup_game (MIN_BOARD_SIZE - 1, MIN_BOARD_SIZE - 1, 0, 15)); 592 gbn_assert (!setup_game (MAX_BOARD_SIZE, MAX_BOARD_SIZE, -1, 15)); 593 594 gbn_assert (setup_game (MAX_BOARD_SIZE, MAX_BOARD_SIZE, 1, 1)); 595 gbn_assert (save_game (DEFAULT_SAVE_DIR "/t1.sgf")); 596 gbn_assert (load_game (DEFAULT_SAVE_DIR "/t1.sgf")); 597 gbn_assert (save_game (DEFAULT_SAVE_DIR "/t2.sgf")); 598 gbn_assert (load_game (DEFAULT_SAVE_DIR "/t2.sgf")); 599 600 gbn_assert (!save_game ("/DIR_DOESNT_EXIST/blah.sgf")); 601 gbn_assert (!load_game ("/DIR_DOESNT_EXIST/blah.sgf")); 602 gbn_assert (!load_game (DEFAULT_SAVE_DIR "/DOESNT_EXIST.sgf")); 603 604 605 606 /* test of a long game, captures, illegal moves */ 607 gbn_assert (load_game (DEFAULT_SAVE_DIR "/long.sgf")); 608 while (move_num < 520) 609 { 610 gbn_assert (num_variations_sgf () == 1); 611 gbn_assert (redo_node_sgf ()); 612 } 613 614 gbn_assert (play_move_sgf (POS (2, 0), BLACK)); 615 gbn_assert (play_move_sgf (POS (2, 1), WHITE)); 616 617 gbn_assert (move_num == 522); 618 619 gbn_assert (white_captures == 261 && black_captures == 0); 620 621 gbn_assert (play_move_sgf (PASS_POS, BLACK)); 622 gbn_assert (play_move_sgf (PASS_POS, WHITE)); 623 624 gbn_assert (move_num == 524); 625 626 int x, y; 627 int b_count, w_count, e_count; 628 b_count = w_count = e_count = 0; 629 for (x = 0; x < 19; ++x) 630 { 631 for (y = 0; y < 19; ++y) 632 { 633 gbn_assert (!legal_move_board (POS (x, y), BLACK, false)); 634 gbn_assert (!play_move_sgf (POS (x, y), BLACK)); 635 switch (get_point_board (POS (x, y))) 636 { 637 case BLACK: 638 ++b_count; 639 break; 640 case WHITE: 641 ++w_count; 642 break; 643 case EMPTY: 644 ++e_count; 645 break; 646 default: 647 gbn_assert (false); 648 } 649 } 650 } 651 652 gbn_assert (b_count == 0 && w_count == 261 && e_count == 19 * 19 - 261); 653 654 gbn_assert (undo_node_sgf ()); 655 gbn_assert (move_num == 523); 656 657 int infinite_prevention = 0; 658 while (move_num > 0) 659 { 660 gbn_assert (undo_node_sgf ()); 661 662 ++infinite_prevention; 663 gbn_assert (infinite_prevention < 100000); 664 } 665 666 gbn_assert (save_game (DEFAULT_SAVE_DIR "/long_out.sgf")); 667 668 669 /* test of basic moves, legal moves, adding and removing stones */ 670 gbn_assert (setup_game (MAX_BOARD_SIZE, MAX_BOARD_SIZE, 0, 0)); 671 gbn_assert (play_move_sgf 672 (POS (MAX_BOARD_SIZE / 2, MAX_BOARD_SIZE / 2), BLACK)); 673 gbn_assert (move_num == 1 && current_player == WHITE); 674 gbn_assert (!legal_move_board 675 (POS (MAX_BOARD_SIZE / 2, MAX_BOARD_SIZE / 2), WHITE, true)); 676 677 int saved_node = current_node; 678 gbn_assert (add_stone_sgf (POS (0, 0), BLACK)); 679 gbn_assert (current_node != saved_node); 680 gbn_assert (get_point_board (POS (0, 0)) == BLACK); 681 gbn_assert (move_num == 1 && current_player == WHITE); 682 683 saved_node = current_node; 684 gbn_assert (add_stone_sgf (POS (0, 1), WHITE)); 685 gbn_assert (current_node == saved_node); 686 gbn_assert (get_point_board (POS (0, 1)) == WHITE); 687 688 gbn_assert (add_stone_sgf (POS (0, 0), EMPTY)); 689 gbn_assert (add_stone_sgf (POS (0, 1), EMPTY)); 690 gbn_assert (get_point_board (POS (0, 0)) == EMPTY); 691 gbn_assert (get_point_board (POS (0, 1)) == EMPTY); 692 693 694 /* test captures */ 695 gbn_assert (load_game (DEFAULT_SAVE_DIR "/cap.sgf")); 696 gbn_assert (play_move_sgf (POS (0, 0), BLACK)); 697 gbn_assert (black_captures == 8); 698 gbn_assert (undo_node_sgf ()); 699 gbn_assert (black_captures == 0); 700 701 gbn_assert (!play_move_sgf (POS (0, 0), WHITE)); 702 play_mode = MODE_FORCE_PLAY; 703 gbn_assert (play_move_sgf (POS (0, 0), WHITE)); 704 play_mode = MODE_PLAY; 705 706 gbn_assert (black_captures == 9); 707 gbn_assert (get_point_board (POS (0, 0)) == EMPTY); 708 gbn_assert (undo_node_sgf ()); 709 gbn_assert (black_captures == 0); 710 711 gbn_assert (play_move_sgf (POS (9, 9), BLACK)); 712 gbn_assert (black_captures == 44); 713 714 for (x = 0; x < 19; ++x) 715 { 716 for (y = 0; y < 19; ++y) 717 { 718 gbn_assert (get_point_board (POS (x, y)) == BLACK || 719 add_stone_sgf (POS (x, y), BLACK)); 720 } 721 } 722 723 gbn_assert (get_point_board (POS (0, 0)) == BLACK); 724 gbn_assert (add_stone_sgf (POS (9, 9), EMPTY)); 725 gbn_assert (play_move_sgf (POS (9, 9), WHITE)); 726 gbn_assert (white_captures == 360); 727 728 gbn_assert (undo_node_sgf ()); 729 gbn_assert (white_captures == 0); 730 731 play_mode = MODE_FORCE_PLAY; 732 gbn_assert (play_move_sgf (POS (9, 9), BLACK)); 733 play_mode = MODE_PLAY; 734 gbn_assert (white_captures == 361); 735 736 for (x = 0; x < 19; ++x) 737 { 738 for (y = 0; y < 19; ++y) 739 { 740 gbn_assert (get_point_board (POS (x, y)) == EMPTY); 741 } 742 } 743 744 745 /* test ko */ 746 gbn_assert (setup_game (MAX_BOARD_SIZE, MAX_BOARD_SIZE, 0, 15)); 747 748 /* 749 * Set up the board to look like this: 750 * -X------ 751 * XO------ 752 * O------- 753 * -------- 754 */ 755 gbn_assert (add_stone_sgf (POS (0, 1), BLACK)); 756 gbn_assert (add_stone_sgf (POS (1, 0), BLACK)); 757 gbn_assert (add_stone_sgf (POS (1, 1), WHITE)); 758 gbn_assert (add_stone_sgf (POS (0, 2), WHITE)); 759 760 /* take the ko and make sure black can't take back */ 761 gbn_assert (play_move_sgf (POS (0, 0), WHITE)); 762 gbn_assert (!play_move_sgf (POS (0, 1), BLACK)); 763 764 /* make sure white can fill, even with the ko_pos set */ 765 gbn_assert (play_move_sgf (POS (0, 1), WHITE)); 766 /* and make sure undo sets the ko again */ 767 gbn_assert (undo_node_sgf ()); 768 gbn_assert (!play_move_sgf (POS (0, 1), BLACK)); 769 770 /* make sure ko threats clear the ko */ 771 gbn_assert (play_move_sgf (POS (2, 2), BLACK)); /* ko threat */ 772 gbn_assert (play_move_sgf (POS (2, 3), WHITE)); /* response */ 773 gbn_assert (play_move_sgf (POS (0, 1), BLACK)); /* take ko */ 774 775 gbn_assert (undo_node_sgf ()); 776 gbn_assert (undo_node_sgf ()); 777 gbn_assert (undo_node_sgf ()); 778 779 /* make sure a pass is counted as a ko threat */ 780 gbn_assert (!play_move_sgf (POS (0, 1), BLACK)); 781 gbn_assert (play_move_sgf (PASS_POS, BLACK)); 782 gbn_assert (play_move_sgf (PASS_POS, WHITE)); 783 gbn_assert (play_move_sgf (POS (0, 1), BLACK)); 784 785 /* and finally let's make sure that white can't directly retake */ 786 gbn_assert (!play_move_sgf (POS (0, 0), WHITE)); 787 788 789 790 /* test some header information saving/loading as well as comment 791 saving loading */ 792 char some_comment[] = 793 "blah blah blah i am a stupid comment. here's some annoying characters: 01234567890!@#$%^&*()[[[[\\\\\\]ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 794 /* that bit near the end is literally this: \\\] which tests escaping 795 of ]s */ 796 char read_buffer[256]; 797 798 gbn_assert (setup_game (MAX_BOARD_SIZE, MAX_BOARD_SIZE, 5, -20)); 799 800 /* this also tests that ko_pos is reset by setuping up a new game */ 801 gbn_assert (play_move_sgf (POS (0, 0), WHITE)); 802 gbn_assert (write_comment_sgf (some_comment) > 0); 803 gbn_assert (play_move_sgf (POS (0, 1), BLACK)); 804 rb->strcpy (header.black, "Jack Black"); 805 rb->strcpy (header.white, "Jill White"); 806 807 gbn_assert (save_game (DEFAULT_SAVE_DIR "/head.sgf")); 808 809 gbn_assert (setup_game (MIN_BOARD_SIZE, MIN_BOARD_SIZE, 1, 1)); 810 gbn_assert (load_game (DEFAULT_SAVE_DIR "/head.sgf")); 811 812 gbn_assert (header.komi == -20 && header.handicap == 5); 813 gbn_assert (board_width == MAX_BOARD_SIZE 814 && board_height == MAX_BOARD_SIZE); 815 gbn_assert (rb->strcmp (header.black, "Jack Black") == 0); 816 gbn_assert (rb->strcmp (header.white, "Jill White") == 0); 817 gbn_assert (redo_node_sgf ()); 818 gbn_assert (read_comment_sgf (read_buffer, sizeof (read_buffer))); 819 gbn_assert (rb->strcmp (read_buffer, some_comment) == 0); 820 gbn_assert (redo_node_sgf ()); 821 gbn_assert (get_point_board (POS (0, 0)) == WHITE); 822 gbn_assert (get_point_board (POS (0, 1)) == BLACK); 823 824 825 826 /* test saving and loading a file with unhandled SGF properties. this 827 test requires that the user diff unhnd.sgf with unhnd_out.sgf (any 828 substantial difference is a bug and should be reported) the 829 following are NOT substantial differences: - reordering of 830 properties in a node - whitespace changes outside of a comment 831 value or other property value - reordering of property values */ 832 gbn_assert (load_game (DEFAULT_SAVE_DIR "/unhnd.sgf")); 833 gbn_assert (save_game (DEFAULT_SAVE_DIR "/unhnd_out.sgf")); 834 835 836 837 /* Test variations a bit */ 838 gbn_assert (setup_game (MAX_BOARD_SIZE, MAX_BOARD_SIZE, 0, 13)); 839 /* start at a move, otherwise add_stone won't create a variation */ 840 gbn_assert (play_move_sgf (POS (5, 5), BLACK)); 841 /* make sure it doesn't */ 842 gbn_assert (undo_node_sgf ()); 843 gbn_assert (add_stone_sgf (POS (4, 5), WHITE)); 844 gbn_assert (!undo_node_sgf ()); 845 gbn_assert (num_variations_sgf () == 1); 846 gbn_assert (play_move_sgf (POS (5, 5), BLACK)); 847 848 gbn_assert (play_move_sgf (POS (0, 0), BLACK)); 849 gbn_assert (num_variations_sgf () == 1); 850 gbn_assert (undo_node_sgf ()); 851 gbn_assert (play_move_sgf (POS (0, 1), BLACK)); 852 gbn_assert (num_variations_sgf () == 2); 853 gbn_assert (undo_node_sgf ()); 854 gbn_assert (play_move_sgf (POS (0, 1), BLACK)); 855 gbn_assert (num_variations_sgf () == 2); 856 gbn_assert (undo_node_sgf ()); 857 gbn_assert (play_move_sgf (POS (0, 2), BLACK)); 858 gbn_assert (num_variations_sgf () == 3); 859 gbn_assert (undo_node_sgf ()); 860 gbn_assert (play_move_sgf (POS (0, 3), WHITE)); 861 gbn_assert (num_variations_sgf () == 4); 862 gbn_assert (undo_node_sgf ()); 863 gbn_assert (play_move_sgf (PASS_POS, BLACK)); 864 gbn_assert (num_variations_sgf () == 5); 865 gbn_assert (undo_node_sgf ()); 866 gbn_assert (add_stone_sgf (POS (1, 1), BLACK)); 867 gbn_assert (add_stone_sgf (POS (1, 2), BLACK)); 868 gbn_assert (add_stone_sgf (POS (1, 3), WHITE)); 869 gbn_assert (num_variations_sgf () == 6); 870 gbn_assert (undo_node_sgf ()); 871 gbn_assert (add_stone_sgf (POS (1, 1), BLACK)); 872 gbn_assert (add_stone_sgf (POS (1, 2), BLACK)); 873 gbn_assert (add_stone_sgf (POS (1, 3), WHITE)); 874 gbn_assert (num_variations_sgf () == 7); 875 gbn_assert (next_variation_sgf ()); 876 gbn_assert (get_point_board (POS (0, 0)) == BLACK); 877 gbn_assert (get_point_board (POS (0, 1)) == EMPTY); 878 gbn_assert (get_point_board (POS (0, 2)) == EMPTY); 879 gbn_assert (get_point_board (POS (1, 1)) == EMPTY); 880 gbn_assert (get_point_board (POS (1, 2)) == EMPTY); 881 gbn_assert (get_point_board (POS (1, 3)) == EMPTY); 882 883 rb->splash (10 * HZ, "All tests passed. Exiting"); 884} 885#endif /* GBN_TEST */