PraktikumOthello/mcp.cc

136 lines
3.3 KiB
C++

/* -*- Mode: C -*- */
#include "mcp_shared.cc"
static bool
fork_player(char *executable, struct player *the_player)
{
enum { READ = 0, WRITE = 1};
int pipe_out[2];
int pipe_in[2];
if (pipe(pipe_out) != 0) return false;
if (pipe(pipe_in) != 0) return false;
if ((the_player->pid = fork()) == -1) abort();
if (the_player->pid == 0) {
/* Child */
close(pipe_out[READ]);
close(pipe_in [WRITE]);
dup2(pipe_in [READ], CHILD_IN_FD);
dup2(pipe_out[WRITE], CHILD_OUT_FD);
setrlimit(RLIMIT_CPU, &cpu_limit);
setrlimit(RLIMIT_AS, &mem_limit);
execl(executable, executable, 0);
perror("execl");
_exit(EXEC_FAILED);
} else {
/* Parent */
/* Stop the player until it is his turn. */
if (kill(the_player->pid, SIGSTOP) < 0)
return false;
/* Close useless ends of pipes */
close(pipe_out[WRITE]);
close(pipe_in [READ]);
the_player->pipe_from_player = pipe_out[READ];
the_player->pipe_to_player = pipe_in[WRITE];
}
return true;
}
int
main(int argc, char **argv)
{
char const *init_state = "O...........................OX......XO...........................";
fprintf(stderr, "Master Control Program\n");
int opt;
while ((opt = getopt(argc, argv, "dT:t:m:M:s:")) != -1) {
switch (opt) {
case 'd': debug = true; break;
case 't': cpu_limit.rlim_cur = strtoul(optarg, NULL, 0); break;
case 'T': cpu_limit.rlim_max = strtoul(optarg, NULL, 0); break;
case 'm': mem_limit.rlim_cur = strtoul(optarg, NULL, 0) << 20; break;
case 'M': mem_limit.rlim_max = strtoul(optarg, NULL, 0) << 20; break;
case 's': init_state = optarg; break;
case ':':
case '?':
goto usage;
}
}
if (optind + 2 > argc) {
usage:
print_usage();
exit(1);
}
setup_signal_handlers();
if (!fork_player(argv[optind], &player[0]) ||
!fork_player(argv[optind + 1], &player[1]))
exit_msg(EXEC_FAILED, "Unable to fork players.\n");
game_state state;
initialize_state(&state, init_state);
idx_t player_no = state.player() == PLAYER_1 ? 0 : 1;
while (!is_final_state(&state)) {
game_move move;
state.player(static_cast<int>(player_no));
char timeBuf[64];
getTimeStr(timeBuf, 64);
printf("[%s] P%u's turn.\nState:\n", timeBuf, player_no);
fflush(stdout);
state.dump_to_stdio();
//serialize_state(STDOUT_FILENO, &state);
printf("\n");
if (!player_move(&player[player_no], &state, &move)) {
if (debug) {
printf("No move from player %d.\n", player_no);
continue;
}
exit_msg(exit_reason(CRASH_0 + player_no),
"No move from player %u.\n", player_no);
}
if (!apply_move(&state, &move)) {
printf("Invalid move from player %u.\n", player_no);
exit_msg(exit_reason(INVALID_MOVE_0 + player_no),
"Invalid move from player %u.\n", player_no);
}
printf("P%u moves.\n", player_no);
player_no = 1 - player_no;
}
printf("\nFinal state:\n");
fflush(stdout);
serialize_state(STDOUT_FILENO, &state);
fprintf(stderr, "\n\nEnd of Line.\n");
printf("\nFinal result: %d : %d\n", state.count_of_type(PLAYER_1),
state.count_of_type(PLAYER_2));
/* Kill players */
for (int i = 0; i < 2; i++) {
int status;
kill(player[i].pid, SIGTERM);
kill(player[i].pid, SIGCONT);
waitpid(player[i].pid, &status, 0);
}
return 0;
}