136 lines
3.3 KiB
C++
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;
|
|
}
|