summaryrefslogtreecommitdiff
path: root/src/pptdb.c
blob: e335d8e438e012545229df3ffad7c081c6d8b1d5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <tak.h>

uint64_t heights[16];

// Warning: performs _no_ checks on input whatsoever
static enum E_RESULT
parse_line(char *pt, const ssize_t read) {
  ssize_t idx = 0;
  enum E_RESULT r;
  for(;;) {
    if (pt[idx] == 'P') {
      // P [A-F][1-6] [CF]?,
      idx+=2;
      enum STONE_VARIANT stone;
      const uint8_t col = pt[idx]-'A', row = pt[idx+1]-'1';

      if (idx + 3 < read) {
        switch (pt[idx+3]) {
          case 'W': { stone = STONE_STANDING; break; }
          case 'C': { stone = STONE_CAPSTONE; break; }
          default:  { stone = STONE_FLAT;     break; }
        }
      } else { stone = STONE_FLAT; }

      /* char buf[100]; */
      /* generate_place(board_size, THE_COORDS(col,row), stone, buf); */
      /* puts(buf); */

      r = try_place(THE_COORDS(col,row), current_colour, stone);
      if (r != ACT_OK) return r;
    } else if (pt[idx] == 'M') {
      // M [A-F][1-6] [A-F][1-6]( [1-6])+,
      idx+=2;
      uint8_t drops[board_size];
      const uint8_t s_col =pt[idx]-'A', s_row=pt[idx+1]-'1',
        d_col=pt[idx+3]-'A', d_row=pt[idx+4]-'1';
      idx+=4;

      enum MOVE_DIRECTION dir;
      if (s_col < d_col) dir=M_RIGHT;
      else if (s_col > d_col) dir=M_LEFT;
      else if (s_row < d_row) dir=M_UP;
      else if (s_row > d_row) dir=M_DOWN;

      uint8_t steps = 0;
      do {
        idx+=2;
        drops[steps++] = pt[idx] - '0';
      } while (idx+2<read && pt[idx+1] != ',');

      /* char buf[100]; */
      /* generate_move(board_size, THE_COORDS(s_col,s_row), dir, steps, drops, buf); */
      /* puts(buf); */

      r = try_move(THE_COORDS(s_col, s_row), dir, steps, drops);

      if (r != ACT_OK) return r;

      // Measure height of stacks exceeding 1
      for (int k = 0; k < board_size * board_size; k++) {
        if (COUNT_AT(k)>1) heights[COUNT_AT(k)]+=1;
      }
    }
    while (idx<read && pt[idx++]!=',');
    if (idx>=read) return ACT_OK;
    next_ply();
  }
  return ACT_OK;
}


int
main(int argc, char **argv) {
  (void)(argc);

  enum E_RESULT r;
  enum WIN_TYPE win;
  uint32_t games = 0, overflow=0, illegal = 0;
  uint32_t road_wins=0, flat_wins=0, road_turns=0, flat_turns=0;

  for (int k = 0; k < 16; k++) heights[k] = 0;

  FILE *playtak;
  ssize_t read;
  size_t len = 0;
  char *line = NULL;

  const uint8_t size = argv[1][0]-'0';
  playtak = fopen(argv[2], "r");
  if (playtak == NULL) exit(EXIT_FAILURE);

  while ((read = getline(&line, &len, playtak)) != -1) {
    reset_state(size);
    r = parse_line(line,read);
    if (r == ACT_ILLEGAL) {
      illegal++;
      printf("Culprit: (%ld) %s",read,line);
    } else if (r == ACT_OVERFLOW) {
      overflow++;
    } else {
      win = check_win();
      if (win == WIN_FLAT_BLACK || win == WIN_FLAT_WHITE || win == WIN_DRAW) {
        flat_wins++;
        flat_turns += ply/2+1;
      } else if (win == WIN_DRAGON || win == WIN_ROAD_BLACK || win == WIN_ROAD_WHITE){
        road_wins++;
        road_turns += ply/2+1;
      }
    }
    games++;
  }

  fclose(playtak);
  if (line) free(line);

  printf("Read %d games\n",games);
  printf("Illegals:  %d\nOverflows: %d\nRoad wins: %d\nFlat wins: %d\n\
Average turns to road win: %.3f\nAverage turns to flat win: %f\n",
         illegal,overflow, road_wins, flat_wins,
         (double)(road_turns)/(double)(road_wins),
         (double)(flat_turns)/(double)(flat_wins));
  for (int k = 2; k < 16; k++) {
    printf("Height %2d: %7ld\n",k,heights[k]);
  }

  exit(EXIT_SUCCESS);
}