From eed9669db9c95228dddd9147630ee1ab06b02560 Mon Sep 17 00:00:00 2001 From: oysteini Date: Sat, 11 Oct 2008 15:30:33 +0000 Subject: [PATCH] more than two clients at the same time --- src/server.c | 410 ++++++++++++++++++++++++++++++++++++--------------- src/server.h | 5 + 2 files changed, 296 insertions(+), 119 deletions(-) diff --git a/src/server.c b/src/server.c index a23b37c..11ced31 100644 --- a/src/server.c +++ b/src/server.c @@ -4,98 +4,112 @@ #include #include #include +#include +#include "server.h" #include "net.h" #include "game.h" #include "asciiart.h" -#define MAX_MSG_LEN 50 -/* -typedef enum { MSG_MOVE, MSG_ROTATE } message_type_t; +typedef struct { + int players[2]; + game_t game; +} server_game_t; + +server_game_t *server_games[MAX_GAMES]; +int server_games_sz; typedef struct { - message_type_t type; - union { - struct { - int row, col; - dir_t dir; - } move; - struct { - int row, col; - rot_t dir; - } rotate; - } args; -} message_t; + int connected; + char name[10]; + int game; + int requested_game, requested_game_with; +} server_client_t; + +server_client_t server_clients[MAX_CLIENTS]; + +typedef int cmdfunc_t(int client, char **args); +typedef struct { + char *name; + char *desc; + int argc; + cmdfunc_t *func; +} server_cmd_t; + +int server_do_command(int clientid, char *cmd); int -read_message(int side, message_t *m) +server_new_game(int silver, int red) +{ + if (server_games_sz == MAX_GAMES) + return -1; + int game_id = server_games_sz++; + server_game_t *g = malloc(sizeof(server_game_t)); + + g->players[SILVER] = silver; + g->players[RED] = red; + server_clients[silver].game = game_id; + server_clients[red].game = game_id; + server_clients[silver].requested_game = 0; + server_clients[red].requested_game = 0; + + init_game(&g->game); + setup_board(&g->game, classic_setup); + server_games[game_id] = g; + return game_id; +} + +void +server_delete_game(int id) { - char buf[MAX_MSG_LEN+1]; - char c; int i; - for (i = 0; i < MAX_MSG_LEN+1; i++) { - c = net_getc(side); - printf("input '%c'\n", c); - if (c == '\n') - break; - buf[i] = c; - } - buf[i] = '\0'; - while (c != '\n') c = net_getc(side); - - switch (buf[0]) { - case 'M': m->type = MSG_MOVE; break; - case 'R': m->type = MSG_ROTATE; break; - default: return E_UNKNOWN_COMMAND; - } - - if (m->type == MSG_MOVE) { - m->args.move.row = buf[2]-'A'; - m->args.move.col = buf[3]-'0'; - switch (buf[5]) { - case 'N': - m->args.move.dir = (buf[6]=='W' ? D_NW : (buf[6]=='E' ? D_NE : D_N)); - break; - case 'S': - m->args.move.dir = (buf[6]=='W' ? D_SW : (buf[6]=='E' ? D_SE : D_S)); - break; - case 'E': - m->args.move.dir = D_E; - break; - case 'W': - m->args.move.dir = D_W; - break; - } - - net_all_printf("msg: MOVE (%d,%d) %d\n", m->args.move.row, m->args.move.col, - m->args.move.dir); - } else if (m->type == MSG_ROTATE) { - m->args.rotate.row = buf[2]-'A'; - m->args.rotate.col = buf[3]-'0'; - m->args.rotate.dir = (buf[5]=='L' ? R_CCW : R_CW); - } - - return HUGE_SUCCESS; + assert(id >= 0 && id < MAX_GAMES && server_games[id] != NULL); + free(server_games[id]); + server_games[id] = NULL; + for (i = id+1; i < server_games_sz; i++) + server_games[i-1] = server_games[i]; + server_games_sz--; } int -execute_message(game_t *game, message_t msg, int side) +server_get_game_request(int client) { - switch (msg.type) { - case MSG_MOVE: - return move(game, side, - msg.args.move.row, msg.args.move.col, - msg.args.move.dir, 0); - case MSG_ROTATE: - return rotate(game, side, - msg.args.rotate.row, msg.args.rotate.col, - msg.args.rotate.dir); - default: - net_side_printf(side, "unknown command type %d\n", msg.type); - return E_UNKNOWN_COMMAND; + int i; + server_client_t *c = server_clients; + for (i = 0; i < MAX_CLIENTS; i++) { + if (c[i].connected && + c[i].requested_game && + (c[i].requested_game_with == client || + c[i].requested_game_with == -1)) + return i; + } + return -1; +} + +int +server_request_game(int client, int opponent) +{ + int match = 0; + if (server_clients[client].requested_game) + return -1; + if (opponent == -1) { + opponent = server_get_game_request(client); + if (opponent != -1) match = 1; + } else { + match = + server_clients[opponent].requested_game && + (server_clients[opponent].requested_game_with == client || + server_clients[opponent].requested_game_with == -1); + } + if (match) { + server_clients[opponent].requested_game = 0; + return server_new_game(client, opponent); + } else { + server_clients[client].requested_game = 1; + server_clients[client].requested_game_with = opponent; + return -1; } } -*/ void terminal_game(void) @@ -111,7 +125,7 @@ terminal_game(void) printf("%s", aabuf); for (;;) { - printf("%s's move\n", sideinfo[game_turn(&game)].name); + printf("move %d, %s\n", game.move, sideinfo[game_turn(&game)].name); fgets(linebuf, 10, stdin); if (parse_move(linebuf, &move) != HUGE_SUCCESS) { printf("not a valid move description: '%s'\n", linebuf); @@ -122,6 +136,9 @@ terminal_game(void) continue; } + asciiart_small_draw_board(aabuf, &game); + printf("%s", aabuf); + if (game.last_move.type == M_ROTATE) { printf("move: %c%c rotated %s\n", game.last_move.y+'A', @@ -146,9 +163,6 @@ terminal_game(void) game.laser_pos[1]+'A', game.laser_pos[0]+'0'); } - asciiart_small_draw_board(aabuf, &game); - printf("%s", aabuf); - switch (game.winner) { case SILVER: printf("SILVER WINS!\n"); @@ -162,64 +176,109 @@ terminal_game(void) } -game_t game; +void +server_report_game_state(int gameid) +{ + server_game_t *g = server_games[gameid]; + int i; + for (i = 0; i < 2; i++) { + int c = g->players[i]; + + if (g->game.last_move.type == M_ROTATE) { + net_client_printf(c, "move: %c%c rotated %s\n", + g->game.last_move.y+'A', + g->game.last_move.x+'0', + g->game.last_move.dir==R_CW ? "R" : "L"); + } else { + int nx, ny; + move_dest(g->game.last_move, &nx, &ny); + net_client_printf(c, "move: %c%c moved to %c%c\n", + g->game.last_move.y+'A', + g->game.last_move.x+'0', + ny+'A', nx+'0'); + } + + if (g->game.last_hit.piece != NONE) { + net_client_printf(c, "laser hits %s %s at %c%c\n", + sideinfo[g->game.last_hit.side].name, + pieceinfo[g->game.last_hit.piece].name, + g->game.laser_pos[1]+'A', g->game.laser_pos[0]+'0'); + } else { + net_client_printf(c, "laser hits wall at %c%c\n", + g->game.laser_pos[1]+'A', g->game.laser_pos[0]+'0'); + } + + char aabuf[ASCIIART_SMALL_BUFSZ]; + asciiart_small_draw_board(aabuf, &g->game); + net_client_printf(c, "%s", aabuf); + + switch (g->game.winner) { + case SILVER: + net_client_printf(c, "SILVER WINS!\n"); + break; + case RED: + net_client_printf(c, "RED WINS!\n"); + break; + default: + if (g->players[game_turn(&g->game)]==c) + net_client_printf(c, "your turn\n"); + } + } +} void -parse_line(int clientid, char *line) { - move_t move; - if (parse_move(line, &move) != HUGE_SUCCESS) { - net_client_printf(clientid, "not a valid move description: '%s'\n", line); +server_do_move(int clientid, move_t move) +{ + int gameid = server_clients[clientid].game; + server_game_t *g = server_games[gameid]; + int side; + + side = (g->players[1]==clientid); + + switch (perform_move(&g->game, side, move)) { + case HUGE_SUCCESS: + break; + case E_NOT_YOUR_TURN: + net_client_printf(clientid, "not your turn\n"); return; - } - if (perform_move(&game, clientid, move) != HUGE_SUCCESS) { + default: net_client_printf(clientid, "invalid move\n"); return; } + server_report_game_state(gameid); - if (game.last_move.type == M_ROTATE) { - net_all_printf("move: %c%c rotated %s\n", - game.last_move.y+'A', - game.last_move.x+'0', - game.last_move.dir==R_CW ? "R" : "L"); - } else { - int nx, ny; - move_dest(game.last_move, &nx, &ny); - net_all_printf("move: %c%c moved to %c%c\n", - game.last_move.y+'A', - game.last_move.x+'0', - ny+'A', nx+'0'); - } - - if (game.last_hit.piece != NONE) { - net_all_printf("laser hits %s %s at %c%c\n", - sideinfo[game.last_hit.side].name, - pieceinfo[game.last_hit.piece].name, - game.laser_pos[1]+'A', game.laser_pos[0]+'0'); - } else { - net_all_printf("laser hits wall at %c%c\n", - game.laser_pos[1]+'A', game.laser_pos[0]+'0'); - } - - char aabuf[ASCIIART_SMALL_BUFSZ]; - asciiart_small_draw_board(aabuf, &game); - net_all_printf("%s", aabuf); - - switch (game.winner) { + switch (g->game.winner) { case SILVER: - net_all_printf("SILVER WINS!\n"); - exit(0); + server_delete_game(gameid); + break; case RED: - net_all_printf("RED WINS!\n"); - exit(0); + server_delete_game(server_clients[clientid].game); + break; } } +void +parse_line(int clientid, char *line) +{ + server_do_command(clientid, line); +} int player[2]={0, 0}; void server_client_connect(int clientid) { + server_client_t *c = &server_clients[clientid]; + c->connected = 1; + sprintf(c->name, "client%03d", clientid); + c->game = -1; + c->requested_game = 0; + + net_client_printf(clientid, "Welcome to the KHET server\n"); + net_client_printf(clientid, "Say 'play' to play a game\n"); + net_client_printf(clientid, "(you may have to wait for another player)\n"); + + /* assert(clientid<2); player[clientid]=1; if (player[0] && player[1]) { @@ -229,9 +288,122 @@ server_client_connect(int clientid) { asciiart_small_draw_board(aabuf, &game); net_all_printf("%s", aabuf); } + */ } +void +server_init(void) +{ + int i; + server_games_sz = 0; + for (i = 0; i < MAX_CLIENTS; i++) + server_clients[i].connected = 0; +} + + + +int +server_cmd_play(int client, char **args) +{ + int g = server_request_game(client, -1); + if (g == -1) { + net_client_printf(client, "requested game with anyone\n"); + } else { + server_report_game_state(g); + } + return 1; +} + +int +server_cmd_playwith(int client, char **args) +{ + net_client_printf(client, "sorry, this is not implemented yet\n"); + return 1; +} + +int +server_cmd_nick(int client, char **args) +{ + net_client_printf(client, "sorry, this is not implemented yet\n"); + return 1; +} + +int +server_cmd_ls(int client, char **args) +{ + net_client_printf(client, "sorry, this is not implemented yet\n"); + return 1; +} + +server_cmd_t server_commands[] = { + { .name = "PLAY", + .desc = "play a game with anyone", + .argc = 0, + .func = server_cmd_play }, + { .name = "PLAYWITH", + .desc = "play a game with a named opponent", + .argc = 1, + .func = server_cmd_playwith }, + { .name = "NICK", + .desc = "set your nickname", + .argc = 1, + .func = server_cmd_nick }, + { .name = "LS", + .desc = "list stuff", + .argc = 1, + .func = server_cmd_ls } }; +int server_commands_sz = 4; + +int +server_do_command(int clientid, char *cmd) +{ + char *cmd_copy = strdup(cmd); + server_cmd_t *cmd_type = NULL; + char *args[10]; + int argc; + char *c; + move_t move; + int i; + + for (i = 0; i < strlen(cmd_copy); i++) { + cmd_copy[i] = toupper(cmd_copy[i]); + } + + if (server_clients[clientid].game != -1 && + parse_move(cmd_copy, &move) == HUGE_SUCCESS) { + server_do_move(clientid, move); + return 1; + } + + for (argc = 0, c = cmd_copy; ; argc++) { + while (*c != ' ' && *c != '\n' && *c != '\0') + c++; + if (*c == ' ' || *c == '\n') *(c++) = '\0'; + while (*c == ' ' || *c == '\n') + c++; + if (*c == '\n' || *c == '\0') + break; + args[argc] = c; + } + + for (i = 0; i < server_commands_sz; i++) { + if (strcmp(cmd_copy, server_commands[i].name)==0) + cmd_type = &server_commands[i]; + } + if (cmd_type == NULL) { + net_client_printf(clientid, "unknown command %s\n", cmd_copy); + return 0; + } + if (argc != cmd_type->argc) { + net_client_printf(clientid, + "wrong number of arguments for %s (wanted %d, got %d)\n", + cmd_type->name, cmd_type->argc, argc); + return 0; + } + + return cmd_type->func(clientid, args); +} int main(int argc, char **argv) { diff --git a/src/server.h b/src/server.h index aa3fe22..91ddae5 100644 --- a/src/server.h +++ b/src/server.h @@ -1,4 +1,9 @@ +#ifndef KHET_SERVER_H +#define KHET_SERVER_H +#define MAX_GAMES 10 void server_client_connect(int clientid); void parse_line(int clientid, char *line); + +#endif