Untitled
unknown
c_cpp
3 years ago
9.7 kB
3
Indexable
#include "status.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.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
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;
}
void receieve(int target, int fd, char* id, int child){
if(read(fd, &(child_status[child]), sizeof(Status)) < 0) debug("read error\n");
writelogfile(target, id, child);
return;
}
void send(int target, int fd, char* id, int child){
writelogfile(target, id, child);
if(write(fd, &(child_status[child]), sizeof(Status)) < 0) debug("write error\n");
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 exec player %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 exec player %s\n", argv[1], child_id[1]);
execl("./player", "./player", child_id[1], pidstr, NULL);
}
}
}
fprintf(stderr, "%s after fork\n", argv[1]);
// parent
close(pipe_fd[0][1]); close(pipe_fd[1][0]); close(pipe_fd[2][1]); close(pipe_fd[3][0]);
fprintf(stderr, "%s INIT end\n", argv[1]);
mode = WAITING;
break;
case WAITING:
// pipe from left child
receieve(0, pipe_fd[0][0], argv[1], 0);
fprintf(stderr, "%s read left child\n", argv[1]);
child_status[0].current_battle_id = argv[1][0];
// pipe from right child
receieve(0, pipe_fd[2][0], argv[1], 1);
fprintf(stderr, "%s read right child\n", argv[1]);
child_status[1].current_battle_id = argv[1][0];
mode = PLAYING;
break;
case PLAYING:
fprintf(stderr, "%s PLAYING\n", argv[1]);
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){
diedchild[1] = 1;
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){
diedchild[0] = 1;
waitpid(child_pid[0], end, 0);
exit(0);
}
}
break;
}
}
return 0;
}Editor is loading...