248 lines
5.3 KiB
C
248 lines
5.3 KiB
C
/* -*- c-basic-offset: 4 -*- */
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <string.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 {
|
|
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
|
|
read_message(int side, message_t *m)
|
|
{
|
|
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;
|
|
}
|
|
|
|
int
|
|
execute_message(game_t *game, message_t msg, int side)
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
*/
|
|
|
|
void
|
|
terminal_game(void)
|
|
{
|
|
game_t game;
|
|
move_t move;
|
|
char aabuf[ASCIIART_SMALL_BUFSZ];
|
|
char linebuf[10];
|
|
|
|
init_game(&game);
|
|
setup_board(&game, classic_setup);
|
|
asciiart_small_draw_board(aabuf, &game);
|
|
printf("%s", aabuf);
|
|
|
|
for (;;) {
|
|
printf("%s's move\n", 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);
|
|
continue;
|
|
}
|
|
if (perform_move(&game, game_turn(&game), move) != HUGE_SUCCESS) {
|
|
printf("invalid move\n");
|
|
continue;
|
|
}
|
|
|
|
if (game.last_move.type == M_ROTATE) {
|
|
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);
|
|
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) {
|
|
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 {
|
|
printf("laser hits wall at %c%c\n",
|
|
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");
|
|
return;
|
|
case RED:
|
|
printf("RED WINS!\n");
|
|
return;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
game_t game;
|
|
|
|
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);
|
|
return;
|
|
}
|
|
if (perform_move(&game, clientid, move) != HUGE_SUCCESS) {
|
|
net_client_printf(clientid, "invalid move\n");
|
|
return;
|
|
}
|
|
|
|
|
|
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) {
|
|
case SILVER:
|
|
net_all_printf("SILVER WINS!\n");
|
|
exit(0);
|
|
case RED:
|
|
net_all_printf("RED WINS!\n");
|
|
exit(0);
|
|
}
|
|
}
|
|
|
|
|
|
int player[2]={0, 0};
|
|
|
|
void
|
|
server_client_connect(int clientid) {
|
|
assert(clientid<2);
|
|
player[clientid]=1;
|
|
if (player[0] && player[1]) {
|
|
char aabuf[ASCIIART_SMALL_BUFSZ];
|
|
init_game(&game);
|
|
setup_board(&game, classic_setup);
|
|
asciiart_small_draw_board(aabuf, &game);
|
|
net_all_printf("%s", aabuf);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
int
|
|
main(int argc, char **argv) {
|
|
if (argc > 1 && strcmp(argv[1], "local")==0) {
|
|
terminal_game();
|
|
return 0;
|
|
} else {
|
|
net_server(15239);
|
|
for (;;)
|
|
net_poll();
|
|
}
|
|
return 0;
|
|
}
|