Untitled

 avatar
unknown
c_cpp
2 years ago
7.8 kB
2
Indexable
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include "status.h"

#define ERR_EXIT(m)     \
  do {                  \
    perror(m);          \
    exit(EXIT_FAILURE); \
  } while (0)

char buffer[1024];
char msg[20];
char status_msg[5][20];
char PSSM_msg[100];

void parseStatus(Status *status) {
  int id = 0, ptr = 0;
  for (int i = 0; i < msg[i]; i++) {
    if (msg[i] == ' ') {
      strncpy(status_msg[id], &msg[ptr], i - ptr);
      status_msg[id++][i - ptr] = 0;
      ptr = i + 1;
    }
  }
  strncpy(status_msg[id], &msg[ptr], 1);
  status_msg[id++][1] = 0;
  // create status
  status->HP = atoi(status_msg[0]);
  status->ATK = atoi(status_msg[1]);
  if (!strcmp(status_msg[2], "FIRE")) {
    status->attr = FIRE;
  } else if (!strcmp(status_msg[2], "GRASS")) {
    status->attr = GRASS;
  } else {
    status->attr = WATER;
  }
  status->current_battle_id = status_msg[3][0];
  status->battle_ended_flag = atoi(status_msg[4]);
}

void pickOutStatus(int ptr) {
  int msg_len = 0;
  for (int i = ptr; buffer[i] != '\n'; i++) {
    msg_len++;
  }
  strncpy(msg, &buffer[ptr], msg_len);
}

int readFile(Status *status, int id) {
  FILE *fp = fopen("player_status.txt", "r");
  fread(buffer, sizeof(char), 1024, fp);
  int cnt = id, ptr = -1;
  for (int i = 0; buffer[i]; i++) {
    if (cnt == 0) {
      ptr = i;
      break;
    }
    if (buffer[i] == '\n') cnt--;
  }
  fclose(fp);
  return ptr;
}

void generatePSSM(Status *status, int player_id) {
  status->real_player_id = player_id;
  int ptr = readFile(status, player_id);
  pickOutStatus(ptr);
  parseStatus(status);
}

int decideTargetID(char ch) {
  int id = -1;
  switch (ch) {
    case 'G':
      id = 8;
      break;
    case 'I':
      id = 9;
      break;
    case 'D':
      id = 10;
      break;
    case 'H':
      id = 11;
      break;
    case 'J':
      id = 12;
      break;
    case 'E':
      id = 13;
      break;
    case 'B':
      id = 14;
      break;
  }
  return id;
}

int main(int argc, char **argv) {
  int player_id = atoi(argv[1]);
  int parent_pid = atoi(argv[2]);

  // create fifo
  char pathname[20];
  for (int i = 8; i <= 14; i++) {
    snprintf(pathname, 20, "player%d.fifo", i);
    mkfifo(pathname, 0666);
    memset(pathname, 0, sizeof(pathname));
  }

  Status status;
  // if is real player
  if (player_id <= 7 && player_id >= 0) {
    // create log file
    snprintf(pathname, 20, "log_player%d.txt", player_id);
    FILE *logfile_fp = fopen(pathname, "w+");
    // GeneratePSSM
    generatePSSM(&status, player_id);
    int initial_hp = status.HP;
    // join battle, continuously receiving/sending data from/to parent
    char buf[100];

    while (1) {
      // write to log file
      memset(buf, 0, sizeof(buf));
      snprintf(buf, 100, "%d,%d pipe to %c,%d %d,%d,%c,%d\n",
               status.real_player_id, getpid(), status.current_battle_id,
               parent_pid, status.real_player_id, status.HP,
               status.current_battle_id, status.battle_ended_flag);
      fprintf(stderr, "real player pipe to buf: %s", buf);
      fprintf(logfile_fp, "%s", buf);
      // send PSSM to parent
      if (write(STDOUT_FILENO, &status, sizeof(Status)) < 0)
        perror("Error: ");
      // receive PSSM from parent
      if (read(STDIN_FILENO, &status, sizeof(Status)) < 0)
        perror("Error: ");
      // write to log file
      memset(buf, 0, sizeof(buf));
      snprintf(buf, 100, "%d,%d pipe from %c,%d %d,%d,%c,%d\n",
               status.real_player_id, getpid(), status.current_battle_id,
               parent_pid, status.real_player_id, status.HP,
               status.current_battle_id, status.battle_ended_flag);
      fprintf(stderr, "real player pipe from buf: %s", buf);
      fprintf(logfile_fp, "%s", buf);
      // if battle is end (battle_ended_flag)
      if (status.battle_ended_flag == 1) {
        // turn off battle_ended_flag
        status.battle_ended_flag = 0;
        // if is last game
        if (status.current_battle_id == 'A') break;
        // if win
        if (status.HP > 0) {
          // recover half blood
          status.HP += (initial_hp - status.HP) / 2;
        }
        // else (lose)
        else {
          // recover full blood
          status.HP = initial_hp;
          // write to log file (fifo to)
          memset(buf, 0, sizeof(buf));
          int target_id = decideTargetID(status.current_battle_id);
          snprintf(buf, 100, "%d,%d fifo to %d %d,%d\n", status.real_player_id,
                   getpid(), target_id, status.real_player_id, status.HP);
          fprintf(logfile_fp, "%s", buf);
          fprintf(stderr, "fifo to buf: %s", buf);
          // write pssm to agent player (corresponds to current_battle_id by
          // fifo)
          memset(pathname, 0, sizeof(pathname));
          snprintf(pathname, 20, "player%d.fifo", target_id);
          int fd;
          if(open(pathname, O_WRONLY)<0) perror("Error: ");
          if (write(fd, &status, sizeof(status)) < 0)
            perror("Error: ");
          // close logfile and fifo
          fclose(logfile_fp);
          close(fd);
          // exit
          exit(0);
        }
      }
    }
    exit(0);
  }
  // else (agent player)
  else {
    // wait until read something from fifo (inherit status)
    memset(pathname, 0, sizeof(pathname));
    snprintf(pathname, 20, "player%d.fifo", player_id);
    int fd = open(pathname, O_WRONLY), n;
    while (n = read(fd, &status, sizeof(status)) < 0)
      ;
    // open real player's log file
    int rpi = status.real_player_id;  // real player id
    int initial_hp = status.HP;
    memset(pathname, 0, sizeof(pathname));
    snprintf(pathname, 20, "log_player%d.txt", rpi);
    FILE *logfile_fp = fopen(pathname, "w+");
    // write to real player's log file (fifo from)
    char buf[100];
    memset(buf, 0, sizeof(buf));
    snprintf(buf, 100, "%d,%d fifo from %d %d,%d\n", player_id, getpid(), rpi,
             rpi, status.HP);
    fprintf(logfile_fp, "%s", buf);
    fprintf(stderr, "fifo from buf: %s", buf);
    // join battle, continuously receiving/sending data from/to parent
    while (1) {
      // write to log file
      memset(buf, 0, sizeof(buf));
      snprintf(buf, 100, "%d,%d pipe to %c,%d %d,%d,%c,%d\n", player_id,
               getpid(), status.current_battle_id, parent_pid, rpi, status.HP,
               status.current_battle_id, status.battle_ended_flag);
      fprintf(logfile_fp, "%s", buf);
      fprintf(stderr, "agent player pipe to buf: %s", buf);
      // send PSSM to parent
      if (write(STDOUT_FILENO, &status, sizeof(Status)) < 0)
        perror("Error: ");
      // receive PSSM from parent
      if (read(STDIN_FILENO, &status, sizeof(Status)) < 0)
        perror("Error: ");
      // write to log file
      memset(buf, 0, sizeof(buf));
      snprintf(buf, 100, "%d,%d pipe from %c,%d %d,%d,%c,%d\n", player_id,
               getpid(), status.current_battle_id, parent_pid, rpi, status.HP,
               status.current_battle_id, status.battle_ended_flag);
      fprintf(logfile_fp, "%s", buf);
      fprintf(stderr, "agent player pipe from buf: %s", buf);
      // if battle is end (battle_ended_flag)
      if (status.battle_ended_flag == 1) {
        status.battle_ended_flag = 0;
        // if is last game
        if (status.current_battle_id == 'A') break;
        // if win
        if (status.HP > 0) {
          // recover half blood
          status.HP += (initial_hp - status.HP) / 2;
        }
        // else (lose)
        else {
          // close logfile and fifo
          fclose(logfile_fp);
          close(fd);
          // exit
          exit(0);
        }
      }
    }
    exit(0);
  }
  exit(0);
}
Editor is loading...