Untitled
unknown
c_cpp
2 years ago
10 kB
5
Indexable
#include "status.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <poll.h> #include <errno.h> #include <sys/types.h> #include <sys/wait.h> #include <fcntl.h> #include <ctype.h> #define debug(args...) fprintf(stderr, args) typedef enum { INIT, WAITING, PLAYING, PASSING, } Battle_mode; char buf[512]; int pid; char pidstr[15]; int logfile_fd; int parent_pid; char* parent_id; // [0]: left, [1]: right int child_pid[2]; char* child_id[2]; Status child_status[2]; int waitchild[2] = {}; int diedchild[2] = {}; int pipe_fd[4][2]; // [0]: read left, [1]: write left, [2]: read right, [3]: write right struct pollfd poll_fd[2]; int type; // 0: 2 battle, 1: 1 battle 1 player, 2: 2 player int lose; // 0: left lose, 1: right lose int* end; int champion = 0; void writelogfile(int target, char* id, int child){ char buf[512]; if(target == 0) // pipe from child sprintf(buf, "%s,%d pipe from %s,%d %d,%d,%s,%d\n", id, pid, child_id[child], child_pid[child], child_status[child].real_player_id, child_status[child].HP, child_status[child].current_battle_id, child_status[child].battle_ended_flag); else if(target == 1) // pipe to child sprintf(buf, "%s,%d pipe to %s,%d %d,%d,%s,%d\n", id, pid, child_id[child], child_pid[child], child_status[child].real_player_id, child_status[child].HP, child_status[child].current_battle_id, child_status[child].battle_ended_flag); else if(target == 2) // pipe from parent sprintf(buf, "%s,%d pipe from %s,%d %d,%d,%s,%d\n", id, pid, parent_id, parent_pid, child_status[child].real_player_id, child_status[child].HP, child_status[child].current_battle_id, child_status[child].battle_ended_flag); else if(target == 3) // pipe to parent sprintf(buf, "%s,%d pipe to %s,%d %d,%d,%s,%d\n", id, pid, parent_id, parent_pid, child_status[child].real_player_id, child_status[child].HP, child_status[child].current_battle_id, child_status[child].battle_ended_flag); write(logfile_fd, buf, strlen(buf)); return; } void printchampion(int child){ char buf[512]; sprintf(buf, "Champion is P%d\n", child_status[child].real_player_id); write(STDOUT_FILENO, buf, strlen(buf)); champion = 1; return; } int findid(char* id){ switch(id[0]){ case 'A': child_id[0] = "B"; child_id[1] = "C"; parent_id = NULL; return 0; case 'B': child_id[0] = "D"; child_id[1] = "E"; parent_id = "A"; return 0; case 'D': child_id[0] = "G"; child_id[1] = "H"; parent_id = "B"; return 0; case 'E': child_id[0] = "I"; child_id[1] = "J"; parent_id = "B"; return 0; case 'F': child_id[0] = "K"; child_id[1] = "L"; parent_id = "C"; return 0; case 'C': child_id[0] = "F"; child_id[1] = "14"; parent_id = "A"; return 1; case 'K': child_id[0] = "M"; child_id[1] = "10"; parent_id = "F"; return 1; case 'L': child_id[0] = "N"; child_id[1] = "13"; parent_id = "F"; return 1; case 'G': child_id[0] = "0"; child_id[1] = "1"; parent_id = "D"; return 2; case 'H': child_id[0] = "2"; child_id[1] = "3"; parent_id = "D"; return 2; case 'I': child_id[0] = "4"; child_id[1] = "5"; parent_id = "E"; return 2; case 'J': child_id[0] = "6"; child_id[1] = "7"; parent_id = "E"; return 2; case 'M': child_id[0] = "8"; child_id[1] = "9"; parent_id = "K"; return 2; case 'N': child_id[0] = "11"; child_id[1] = "12"; parent_id = "L"; return 2; } } int zone(char* id){ switch(id[0]){ // zone A case 'B': case 'D': case 'E': case 'G': case 'H': case 'I': case 'J': return 1; // zone B case 'A': case 'C': case 'F': case 'K': case 'L': case 'M': case 'N': return 2; } } void openlogfile(char* s){ char buf[20]; sprintf(buf, "log_battle%s.txt", s); logfile_fd = open(buf, O_RDWR | O_CREAT | O_TRUNC | O_APPEND, S_IRWXU | S_IRWXG | S_IRWXO); if(logfile_fd < 0) debug("openlogfile error\n"); return; } struct pollfd newPollfd(int fd, short events){ struct pollfd a; a.fd = fd; a.events = events; a.revents = 0; return a; } void receieve(int target, int fd, char* id, int child){ read(fd, &(child_status[child]), sizeof(Status)); writelogfile(target, id, child); return; } void send(int target, int fd, char* id, int child){ writelogfile(target, id, child); write(fd, &(child_status[child]), sizeof(Status)); return; } int attribute(char* id, Attribute a){ switch(id[0]){ case 'A': case 'E': case 'F': case 'G': case 'M': return (a == FIRE) + 1; case 'B': case 'K': case 'L': case 'H': case 'J': return (a == GRASS) + 1; case 'C': case 'D': case 'I': case 'N': return (a == WATER) +1; } } int subround(char* id, int att, int oth){ // att attack child_status[oth].HP -= child_status[att].ATK * attribute(id, child_status[att].attr); if(child_status[oth].HP <= 0){ child_status[att].battle_ended_flag = child_status[oth].battle_ended_flag = 1; return 1; } return 0; } int playround(char* id){ if((child_status[0].HP < child_status[1].HP) || ((child_status[0].HP == child_status[1].HP) && (child_status[0].real_player_id < child_status[1].real_player_id))){ // left first if(subround(id, 0, 1)) return 1; else if(subround(id, 1, 0)) return 0; }else if(child_status[0].HP > child_status[1].HP || ((child_status[0].HP == child_status[1].HP) && (child_status[0].real_player_id > child_status[1].real_player_id))){ // right first if(subround(id, 1, 0)) return 0; else if(subround(id, 0, 1)) return 1; } return 2; } int main (int argc, char *argv[]) { pid = getpid(); sprintf(pidstr, "%d", pid); Battle_mode mode = INIT; while(diedchild[0] != 1 || diedchild[1] != 1){ switch (mode) { case INIT: openlogfile(argv[1]); type = findid(argv[1]); // pipe for(int i = 0; i < 4; i++) pipe(pipe_fd[i]); fprintf(stderr, "%s after pipe\n", argv[1]); // fork if((child_pid[0] = fork()) < 0) debug("fork error\n"); else if(child_pid[0] == 0){ // left child close(pipe_fd[0][0]); close(pipe_fd[1][1]); close(pipe_fd[2][0]); close(pipe_fd[2][1]); close(pipe_fd[3][0]); close(pipe_fd[3][1]); if(dup2(pipe_fd[0][1], STDOUT_FILENO) != STDOUT_FILENO) debug("dup2 error to stdout\n"); close(pipe_fd[0][1]); if(dup2(pipe_fd[1][0], STDIN_FILENO) != STDIN_FILENO) debug("dup2 error to stdin\n"); close(pipe_fd[1][0]); // exec if(type == 0 || type == 1){ // battle execl("./battle", "./battle", child_id[0], pidstr, NULL); }else if(type == 2){ // player fprintf(stderr, "%s fork child %s\n", argv[1], child_id[0]); execl("./player", "./player", child_id[0], pidstr, NULL); } }else if(child_pid[0] > 0){ // parent fork right child if((child_pid[1] = fork()) < 0) debug("fork error\n"); else if(child_pid[1] == 0){ // right child close(pipe_fd[0][0]); close(pipe_fd[0][1]); close(pipe_fd[1][0]); close(pipe_fd[1][1]); close(pipe_fd[2][0]); close(pipe_fd[3][1]); if(dup2(pipe_fd[2][1], STDOUT_FILENO) != STDOUT_FILENO) debug("dup2 error to stdout\n"); close(pipe_fd[2][1]); if(dup2(pipe_fd[3][0], STDIN_FILENO) != STDIN_FILENO) debug("dup2 error to stdin\n"); close(pipe_fd[3][0]); // exec if(type == 0){ // battle execl("./battle", "./battle", child_id[1], pidstr, NULL); }else if(type == 1 || type == 2){ // player fprintf(stderr, "%s fork player %s\n", argv[1], child_id[1]); execl("./player", "./player", child_id[1], pidstr, NULL); } } } // parent close(pipe_fd[0][1]); close(pipe_fd[1][0]); close(pipe_fd[2][1]); close(pipe_fd[3][0]); poll_fd[0] = newPollfd(pipe_fd[0][0], POLLIN); poll_fd[1] = newPollfd(pipe_fd[2][0], POLLIN); debug(argv[1], "after fork\n"); mode = WAITING; break; case WAITING: poll(poll_fd, 2, -1); if((poll_fd[0].revents & poll_fd[0].events) == POLLIN){ // left child send // pipe from left child receieve(0, poll_fd[0].fd, argv[1], 0); fprintf(stderr, "%s read left child\n", argv[1]); child_status[0].current_battle_id = argv[1][0]; waitchild[0] = 1; poll_fd[0].events = 0; } if((poll_fd[1].revents & poll_fd[1].events) == POLLIN){ // right child send // pipe from right child receieve(0, poll_fd[1].fd, argv[1], 1); fprintf(stderr, "%s read right child\n", argv[1]); child_status[1].current_battle_id = argv[1][0]; waitchild[1] = 1; poll_fd[1].events = 0; } if(waitchild[0] == 1 && waitchild[1] == 1){ waitchild[0] = waitchild[1] = 0; mode = PLAYING; } break; case PLAYING: debug(argv[1], " PLAYING\n"); lose = playround(argv[1]); diedchild[lose] = 1; // pipe to left child send(1, pipe_fd[1][1], argv[1], 0); // pipe to right child send(1, pipe_fd[3][1], argv[1], 1); if(lose != 2){ waitpid(child_pid[lose], end, 0); if(argv[1][0] == 'A'){ // print champion message printchampion(!lose); exit(0); } mode = PASSING; }else{ mode = WAITING; } break; case PASSING: if(lose == 0){ // left lose // pipe from right child receieve(0, pipe_fd[2][0], argv[1], 1); // pipe to parent send(3, STDOUT_FILENO, argv[1], 1); // pipe from parent receieve(2, STDIN_FILENO, argv[1], 1); // pipe to right child send(1, pipe_fd[3][1], argv[1], 1); if(child_status[1].HP <= 0){ waitpid(child_pid[1], end, 0); exit(0); } }else if(lose == 1){ // receive left pssm // pipe from left child receieve(0, pipe_fd[0][0], argv[1], 0); // pipe to parent send(3, STDOUT_FILENO, argv[1], 0); // pipe from parent receieve(2, STDIN_FILENO, argv[1], 0); // pipe to left child send(1, pipe_fd[1][1], argv[1], 0); if(child_status[0].HP <= 0){ waitpid(child_pid[0], end, 0); exit(0); } } break; } } return 0; }
Editor is loading...