Skip to content

Instantly share code, notes, and snippets.

@yjh0502
Last active August 29, 2015 14:27
Show Gist options
  • Save yjh0502/c46c786f13bd46cd1eac to your computer and use it in GitHub Desktop.
Save yjh0502/c46c786f13bd46cd1eac to your computer and use it in GitHub Desktop.
15ai_client_c
#include <netdb.h>
#include <netinet/in.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
const char *team_name = "test-c-client";
#define PORT 25252
#define MSG_TEAM_LENGTH 24
#define BOARD_WIDTH 25
#define BOARD_HEIGHT 13
#define NUM_SLIMES 5
#define MSG_STATE_SIZE (2 + BOARD_WIDTH * BOARD_HEIGHT + NUM_SLIMES * 4)
#define MSG_MOVE_SIZE (2 + NUM_SLIMES)
#define DIR_RIGHT 0
#define DIR_TOP 1
#define DIR_LEFT 2
#define DIR_DOWN 3
#define TEAM_RED 0
#define TEAM_BLUE 1
struct position {
uint8_t x, y;
};
struct game_state {
int team;
int turn;
uint8_t board[BOARD_WIDTH * BOARD_HEIGHT];
struct position slime_positions[NUM_SLIMES * 2];
};
struct action {
uint8_t slime_directions[NUM_SLIMES];
};
static void
make_move(struct game_state *state, struct action *action) {
// XXX: fill here
for(int i = 0; i < 5; i++) {
struct position pos = state->slime_positions[i + state->team*NUM_SLIMES];
fprintf(stderr, "%i: %d %d\n", i, pos.x, pos.y);
if(state->team == TEAM_RED) {
action->slime_directions[i] = DIR_RIGHT;
} else {
action->slime_directions[i] = DIR_LEFT;
}
}
}
static void
exitf(const char *format, ...) {
va_list args;
va_start(args, format);
fprintf(stderr, "error: ");
vfprintf(stderr, format, args);
va_end(args);
exit(EXIT_FAILURE);
}
static int
connect_server(const char *addr, int port) {
int sockfd;
struct sockaddr_in serv_addr;
struct hostent *server;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
exitf("socket\n");
}
server = gethostbyname(addr);
if (server == NULL) {
exitf("gethostbyname\n");
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(port);
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) {
exitf("connect\n");
}
return sockfd;
}
static int
handshake(int fd, const char *team_name, int team) {
char out[MSG_TEAM_LENGTH];
memset(out, 0, MSG_TEAM_LENGTH);
snprintf(out, MSG_TEAM_LENGTH, "%c%s", team, team_name);
ssize_t len = send(fd, out, MSG_TEAM_LENGTH, 0);
if(len != MSG_TEAM_LENGTH) {
exitf("short send: %d != %d\n", len, MSG_TEAM_LENGTH);
}
char in[1];
len = recv(fd, in, 1, MSG_WAITALL);
if(len != 1) {
exitf("short recv: %d != %d\n", len, 1);
}
fprintf(stderr, "team %d\n", in[0]);
return in[0];
}
static void
loop(int fd, int team) {
ssize_t len;
char in[MSG_STATE_SIZE];
char out[MSG_MOVE_SIZE];
if((len = recv(fd, in, MSG_STATE_SIZE, MSG_WAITALL)) != MSG_STATE_SIZE) {
exitf("short recv on loop: %d != %d\n", len, MSG_STATE_SIZE);
}
// turn nubmer is in big endian
uint16_t turn = (in[0] << 8) + in[1];
fprintf(stderr, "turn %d\n", turn);
struct game_state state;
state.turn = turn;
state.team = team;
memcpy(&state.board, in+2, MSG_STATE_SIZE-2);
struct action action;
make_move(&state, &action);
memcpy(out, in, 2);
memcpy(out+2, &action, sizeof(action));
if((len = send(fd, out, MSG_MOVE_SIZE, 0)) != MSG_MOVE_SIZE) {
exitf("short send on loop: %d != %d\n", len, MSG_MOVE_SIZE);
}
}
int main(int argc, char ** argv) {
if(argc < 2) {
exitf("usage: %s hostname\n", argv[0]);
}
int fd = connect_server(argv[1], PORT);
int team = handshake(fd, team_name, 0);
for(;;) {
loop(fd, team);
}
return 0;
}
CFLAGS=-Wall -Werror -Wextra -g -ggdb
main: main.c
gcc $(CFLAGS) $< -o $@
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment