<commit_before>#include <stdio.h>
#include <stddef.h>
#include <sys/types.h>
#include <limits.h>
#include <assert.h>

#define FIELD_LENGTH 3

const unsigned char NO_PLAYER = ' ';

struct game {
  unsigned char field[FIELD_LENGTH * FIELD_LENGTH];
};

struct player {
  unsigned char symbol;
  int (*move_function)(const struct game * g, const unsigned char player);
};

void output(const struct game *g) {
  for (ssize_t j = 0; j < FIELD_LENGTH; j++) {
    for (ssize_t i = 0; i < FIELD_LENGTH; i++) {
      printf("%c%c", g->field[j * FIELD_LENGTH + i],
             (i < (FIELD_LENGTH - 1)) ? '|' : '\n');
    }
    if (j < (FIELD_LENGTH - 1))
      printf("-+-+-\n");
  }
}

void make_clear(struct game *g) {
  for (size_t i = 0; i < sizeof(g->field); i++)
    g->field[i] = NO_PLAYER;
}

_Bool valid_move(const struct game * g, size_t field) {
  return ((field < sizeof(g->field)) && (g->field[field] == NO_PLAYER));
}

unsigned char winner(const struct game *g) {
  /* case 1: --- */
  for (size_t j = 0; j < sizeof(g->field); j += FIELD_LENGTH)
    if (g->field[j] != NO_PLAYER && g->field[j] == g->field[j + 1] &&
        g->field[j] == g->field[j + 2])
      return g->field[j];

  /* case 2: ||| */
  for (ssize_t j = 0; j < FIELD_LENGTH; j++)
    if (g->field[j] != NO_PLAYER &&
        g->field[j] == g->field[FIELD_LENGTH * 1 + j] &&
        g->field[j] == g->field[FIELD_LENGTH * 2 + j])
      return g->field[j];

  /* case 3: /\ */
  if (g->field[0] == g->field[4] && g->field[0] == g->field[8])
    return g->field[0];
  if (g->field[2] == g->field[4] && g->field[2] == g->field[6])
    return g->field[2];

  return NO_PLAYER;
}

_Bool game_is_on(const struct game * g) {
  /* no winner yet */
  if(winner(g) != NO_PLAYER)
    return 0;

  /* still space on board */
  for(size_t i = 0; i < sizeof(g->field); i++) {
    if(g->field[i] == NO_PLAYER)
      return 1;
  }

  return 0;
}

void do_move(const unsigned char player, const size_t move,
             struct game *g) {
  g->field[move] = player;
}

unsigned char other_player(unsigned char player) {
  assert(player == 'x' || player == 'o');
#if 0
  if(player == 'x')
    return 'o';
  else
    return 'x';
#else
  return (player == 'x') ? 'o' : 'x';
#endif
}

int evaluate(const struct game *game, const char player) {
  if (winner(game) == player) {
    return 1;
  } else if (winner(game) == ' ') {
    return 0;
  } else {
    return -1;
  }
}

int miniMax(const struct game *game, const char player, int depth,
            size_t *best_move) {
  if (!game_is_on(game))
    return evaluate(game, player);
  int maxWert = INT_MIN;
  for (size_t move = 0; move < sizeof(game->field); move++) {
    if (!valid_move(game, move))
      continue;

    struct game copy_ = *game;
    do_move(player, move, &copy_);
    int wert =
        -miniMax(&copy_, (player == 'x') ? 'o' : 'x', depth + 1, best_move);
    if (wert > maxWert) {
      maxWert = wert;
      if (depth == 0)
        *best_move = move;
    }
  }
  return maxWert;
}

int get_move(const struct game * g, const unsigned char player) {
  output(g);
  printf("Zug für Spieler '%c'?: ", player);
  fflush(stdout);
  int move = -1;
  scanf("%d", &move);
  return move;
}


int get_smart_computer_move(const struct game * g, const unsigned char player) {
  size_t best_move = 0;
  miniMax(g, player, 0, &best_move);
  return best_move;
}


int get_computer_move(const struct game * g, const unsigned char player) {
  (void)(player);
  for(size_t move = 0; move < sizeof(g->field); move++)
    if(valid_move(g, move))
      return move;

  return 0;
}

int main() {
  struct game g = {
    .field = { 'x', 'o', ' ', 'j', 'k', 'l', 'x', 'x', 'x' }};
  make_clear(&g);

#if 1
  struct player players[] = { { 'x', &get_move }, { 'o', &get_smart_computer_move } };
#else
  struct player players[] = { { 'x', &get_smart_computer_move },
                              { 'o', &get_smart_computer_move } };
#endif
  size_t player_idx = 0;
  while(game_is_on(&g)) {
    struct player * player = &players[player_idx & 1];
    size_t move = player->move_function(&g, player->symbol);
    if(valid_move(&g, move)) {
      do_move(player->symbol, move, &g);
    } else {
      printf("Move %zd of player %c is invalid. Game lost.\n", move, player->symbol);
      return -1;
    }
    if(winner(&g) != NO_PLAYER) {
      printf("Player %c has won.\n", player->symbol);
      output(&g);
      return 0;
    }
    player_idx++;
  }
  printf("Tie.\n");
  output(&g);
}<commit_msg>Improved TicTacToe.<commit_after>#include <stdio.h>
#include <stddef.h>
#include <sys/types.h>
#include <limits.h>
#include <assert.h>

#define FIELD_LENGTH 3

const char NO_PLAYER = 0;

struct game {
  char field[FIELD_LENGTH * FIELD_LENGTH];
};

struct player {
  int (*move_function)(const struct game *g, const char player);
};

char player2symbol(char player) {
  switch (player) {
  case 1:
    return 'x';
  case -1:
    return 'o';
  case 0:
    return ' ';
  default:
    assert(0);
  }
}

void output(const struct game *g) {
  for (ssize_t j = 0; j < FIELD_LENGTH; j++) {
    for (ssize_t i = 0; i < FIELD_LENGTH; i++) {
      printf("%c%c", player2symbol(g->field[j * FIELD_LENGTH + i]),
             (i < (FIELD_LENGTH - 1)) ? '|' : '\n');
    }
    if (j < (FIELD_LENGTH - 1))
      printf("-+-+-\n");
  }
}

void make_clear(struct game *g) {
  for (size_t i = 0; i < sizeof(g->field); i++)
    g->field[i] = NO_PLAYER;
}

_Bool valid_move(const struct game * g, size_t field) {
  return ((field < sizeof(g->field)) && (g->field[field] == NO_PLAYER));
}

char winner(const struct game *g) {
  /* case 1: --- */
  for (size_t j = 0; j < sizeof(g->field); j += FIELD_LENGTH)
    if (g->field[j] != NO_PLAYER && g->field[j] == g->field[j + 1] &&
        g->field[j] == g->field[j + 2])
      return g->field[j];

  /* case 2: ||| */
  for (ssize_t j = 0; j < FIELD_LENGTH; j++)
    if (g->field[j] != NO_PLAYER &&
        g->field[j] == g->field[FIELD_LENGTH * 1 + j] &&
        g->field[j] == g->field[FIELD_LENGTH * 2 + j])
      return g->field[j];

  /* case 3: /\ */
  if (g->field[0] == g->field[4] && g->field[0] == g->field[8])
    return g->field[0];
  if (g->field[2] == g->field[4] && g->field[2] == g->field[6])
    return g->field[2];

  return NO_PLAYER;
}

_Bool game_is_on(const struct game * g) {
  /* no winner yet */
  if(winner(g))
    return 0;

  /* still space on board */
  for(size_t i = 0; i < sizeof(g->field); i++) {
    if(g->field[i] == NO_PLAYER)
      return 1;
  }

  return 0;
}

void do_move(const char player, const size_t move,
             struct game *g) {
  g->field[move] = player;
}

int evaluate(const struct game *game, const char player) {
  return player * winner(game);
}

int miniMax(const struct game *game, const char player, int depth,
            size_t *best_move) {
  if (!game_is_on(game))
    return evaluate(game, player);
  int maxWert = INT_MIN;
  for (size_t move = 0; move < sizeof(game->field); move++) {
    if (!valid_move(game, move))
      continue;

    struct game copy_ = *game;
    do_move(player, move, &copy_);
    int wert =
        -miniMax(&copy_, -1 * player, depth + 1, best_move);
    if (wert > maxWert) {
      maxWert = wert;
      if (depth == 0)
        *best_move = move;
    }
  }
  return maxWert;
}

int get_move(const struct game * g, const char player) {
  output(g);
  printf("Zug für Spieler '%c'?: ", player2symbol(player));
  fflush(stdout);
  int move = -1;
  scanf("%d", &move);
  return move;
}


int get_smart_computer_move(const struct game * g, const char player) {
  size_t best_move = 0;
  miniMax(g, player, 0, &best_move);
  return best_move;
}


int get_computer_move(const struct game * g, const char player) {
  (void)(player);
  for(size_t move = 0; move < sizeof(g->field); move++)
    if(valid_move(g, move))
      return move;

  return 0;
}

int main() {
  struct game g;
  make_clear(&g);

#if 0
  struct player players[] = { { &get_move }, { &get_smart_computer_move } };
#else
  struct player players[] = { {  &get_smart_computer_move },
                              {  &get_smart_computer_move } };
#endif
  char player_idx = 1;
  while(game_is_on(&g)) {
    struct player * player = &players[player_idx < 0];
    size_t move = player->move_function(&g, player_idx);
    if(valid_move(&g, move)) {
      do_move(player_idx, move, &g);
    } else {
      printf("Move %zd of player %c is invalid. Game lost.\n", move,
             player2symbol(player_idx));
      return -1;
    }
    if(winner(&g)) {
      printf("Player %c has won.\n", player2symbol(player_idx));
      output(&g);
      return 0;
    }
    player_idx *= -1;
  }
  printf("Tie.\n");
  output(&g);
}
{'fraction_non_alphanumeric': 0.1811694290976059, 'fraction_numerical': 0.01151012891344383, 'mean_word_length': 2.802625820568928, 'pattern_counts': {'":': 0, '<': 36, '<?xml version=': 0, '>': 87, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1165773', 'n_tokens_mistral': 3386, 'n_tokens_neox': 3287, 'n_words': 856}