static void do_rmc(uint8_t argc, char** argv, Stream *out) { static uint8_t lock_cnt = 4; char buf[95], tbuf[9]; if (argc != 13) /* Ignore if wrong format */ return; if (*argv[2] != 'A') { notify_fix(false); /* Ignore if receiver not in lock */ lock_cnt = 4; return; } else if (lock_cnt > 0) { lock_cnt--; return; } lock_cnt = 1; notify_fix(true); /* get timestamp */ nmea2time(¤t_pos.timestamp, argv[1], argv[9]); /* get latitude [ddmm.mmmmm] */ str2coord(2, argv[3], ¤t_pos.latitude); if (*argv[4] == 'S') current_pos.latitude = -current_pos.latitude; /* get longitude [dddmm.mmmmm] */ str2coord(3, argv[5], ¤t_pos.longitude); if (*argv[6] == 'W') current_pos.longitude = -current_pos.longitude; /* get speed [nnn.nn] */ if (*argv[7] != '\0') sscanf(argv[7], "%f", ¤t_pos.speed); else current_pos.speed = 0; /* get course [nnn.nn] */ if (*argv[8] != '\0') { float x; sscanf(argv[8], "%f", &x); current_pos.course = (uint16_t) x+0.5; } else current_pos.course = 0; current_pos.altitude = altitude; /* If requested, show position on screen */ if (monitor_pos) { sprintf_P(buf, PSTR("TIME: %s, POS: lat=%f, long=%f, SPEED: %f km/h, COURSE: %u deg\r\n"), time2str(tbuf, current_pos.timestamp), current_pos.latitude, current_pos.longitude, current_pos.speed*KNOTS2KMH, current_pos.course); putstr(out, buf); } }
/** * get coordinates * @return 1 if all OK */ int get_telescope_coords(double *ra, double *decl){ double r, d; char *ans; // :GR# -> 11:05:26.16# ans = write_cmd(":GR#"); if(!str2coord(ans, &r)) return 0; // :GD# -> +44:14:10.7# ans = write_cmd(":GD#"); if(!str2coord(ans, &d)) return 0; if(ra) *ra = r; if(decl) *decl = d; return 1; }
static bool test_sar(struct board *b, char *arg) { enum stone color = str2stone(arg); arg += 2; coord_t *cc = str2coord(arg, board_size(b)); coord_t c = *cc; coord_done(cc); arg += strcspn(arg, " ") + 1; int eres = atoi(arg); board_print_test(2, b); if (DEBUGL(1)) printf("sar %s %s %d...\t", stone2str(color), coord2sstr(c, b), eres); assert(board_at(b, c) == S_NONE); int rres = is_bad_selfatari(b, color, c); if (rres == eres) { if (DEBUGL(1)) printf("OK\n"); } else { if (debug_level <= 2) { board_print_test(0, b); printf("sar %s %s %d...\t", stone2str(color), coord2sstr(c, b), eres); } printf("FAILED (%d)\n", rres); } return rres == eres; }
static bool test_useful_ladder(struct board *b, char *arg) { enum stone color = str2stone(arg); arg += 2; coord_t *cc = str2coord(arg, board_size(b)); coord_t c = *cc; coord_done(cc); arg += strcspn(arg, " ") + 1; int eres = atoi(arg); board_print_test(2, b); if (DEBUGL(1)) printf("useful_ladder %s %s %d...\t", stone2str(color), coord2sstr(c, b), eres); assert(board_at(b, c) == S_NONE); group_t atari_neighbor = board_get_atari_neighbor(b, c, color); assert(atari_neighbor); int ladder = is_ladder(b, c, atari_neighbor, true); assert(ladder); int rres = useful_ladder(b, atari_neighbor); if (rres == eres) { if (DEBUGL(1)) printf("OK\n"); } else { if (debug_level <= 2) { board_print_test(0, b); printf("useful_ladder %s %s %d...\t", stone2str(color), coord2sstr(c, b), eres); } printf("FAILED (%d)\n", rres); } return (rres == eres); }
static bool test_moggy_moves(struct board *b, char *arg) { int runs = 1000; coord_t *cc = str2coord(arg, board_size(b)); struct move last; last.coord = *cc; coord_done(cc); last.color = board_at(b, last.coord); assert(last.color == S_BLACK || last.color == S_WHITE); enum stone color = stone_other(last.color); arg += strcspn(arg, " ") + 1; b->last_move = last; board_print(b, stderr); // Always print board so we see last move char e_arg[128]; sprintf(e_arg, "runs=%i", runs); struct engine *e = engine_replay_init(e_arg, b); if (DEBUGL(1)) printf("moggy moves %s, %s to play. Sampling moves (%i runs)...\n\n", coord2sstr(last.coord, b), stone2str(color), runs); int played_[b->size2 + 2]; memset(played_, 0, sizeof(played_)); int *played = played_ + 2; // allow storing pass/resign int most_played = 0; replay_sample_moves(e, b, color, played, &most_played); /* Show moves stats */ for (int k = most_played; k > 0; k--) for (coord_t c = resign; c < b->size2; c++) if (played[c] == k) printf("%3s: %.2f%%\n", coord2str(c, b), (float)k * 100 / runs); engine_done(e); return true; // Not much of a unit test right now =) }
struct fbook * fbook_init(char *filename, struct board *b) { if (fbcache && fbcache->bsize == board_size(b) && fbcache->handicap == b->handicap) return fbcache; FILE *f = fopen(filename, "r"); if (!f) { perror(filename); return NULL; } struct fbook *fbook = calloc(1, sizeof(*fbook)); fbook->bsize = board_size(b); fbook->handicap = b->handicap; /* We do not set handicap=1 in case of too low komi on purpose; * we want to go with the no-handicap fbook for now. */ for (int i = 0; i < 1<<fbook_hash_bits; i++) fbook->moves[i] = pass; if (DEBUGL(1)) fprintf(stderr, "Loading opening fbook %s...\n", filename); /* Scratch board where we lay out the sequence; * one for each transposition. */ struct board *bs[8]; for (int i = 0; i < 8; i++) { bs[i] = board_init(NULL); board_resize(bs[i], fbook->bsize - 2); } char linebuf[1024]; while (fgets(linebuf, sizeof(linebuf), f)) { char *line = linebuf; linebuf[strlen(linebuf) - 1] = 0; // chop /* Format of line is: * BSIZE COORD COORD COORD... | COORD * BSIZE/HANDI COORD COORD COORD... | COORD * We descend up to |, then add the new node * with value minimax(1000), forcing UCT to * always pick that node immediately. */ int bsize = strtol(line, &line, 10); if (bsize != fbook->bsize - 2) continue; int handi = 0; if (*line == '/') { line++; handi = strtol(line, &line, 10); } if (handi != fbook->handicap) continue; while (isspace(*line)) line++; for (int i = 0; i < 8; i++) { board_clear(bs[i]); bs[i]->last_move.color = S_WHITE; } while (*line != '|') { coord_t *c = str2coord(line, fbook->bsize); for (int i = 0; i < 8; i++) { coord_t coord = coord_transform(b, *c, i); struct move m = { .coord = coord, .color = stone_other(bs[i]->last_move.color) }; int ret = board_play(bs[i], &m); assert(ret >= 0); } coord_done(c); while (!isspace(*line)) line++; while (isspace(*line)) line++; } line++; while (isspace(*line)) line++; /* In case of multiple candidates, pick one with * exponentially decreasing likelihood. */ while (strchr(line, ' ') && fast_random(2)) { line = strchr(line, ' '); while (isspace(*line)) line++; // fprintf(stderr, "<%s> skip to %s\n", linebuf, line); } coord_t *c = str2coord(line, fbook->bsize); for (int i = 0; i < 8; i++) { coord_t coord = coord_transform(b, *c, i); #if 0 char conflict = is_pass(fbook->moves[bs[i]->hash & fbook_hash_mask]) ? '+' : 'C'; if (conflict == 'C') for (int j = 0; j < i; j++) if (bs[i]->hash == bs[j]->hash) conflict = '+'; if (conflict == 'C') { hash_t hi = bs[i]->hash; while (!is_pass(fbook->moves[hi & fbook_hash_mask]) && fbook->hashes[hi & fbook_hash_mask] != bs[i]->hash) hi++; if (fbook->hashes[hi & fbook_hash_mask] == bs[i]->hash) hi = 'c'; } fprintf(stderr, "%c %"PRIhash":%"PRIhash" (<%d> %s)\n", conflict, bs[i]->hash & fbook_hash_mask, bs[i]->hash, i, linebuf); #endif hash_t hi = bs[i]->hash; while (!is_pass(fbook->moves[hi & fbook_hash_mask]) && fbook->hashes[hi & fbook_hash_mask] != bs[i]->hash) hi++; fbook->moves[hi & fbook_hash_mask] = coord; fbook->hashes[hi & fbook_hash_mask] = bs[i]->hash; fbook->movecnt++; } coord_done(c); } for (int i = 0; i < 8; i++) { board_done(bs[i]); } fclose(f); if (!fbook->movecnt) { /* Empty book is not worth the hassle. */ fbook_done(fbook); return NULL; } struct fbook *fbold = fbcache; fbcache = fbook; if (fbold) fbook_done(fbold); return fbook; } void fbook_done(struct fbook *fbook) { if (fbook != fbcache) free(fbook); }