Upload files to "/"
This commit is contained in:
commit
827fddf482
359
main.c
Normal file
359
main.c
Normal file
@ -0,0 +1,359 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <irc.h>
|
||||
|
||||
#ifdef ENABLE_SSL
|
||||
#include <openssl/err.h>
|
||||
#endif
|
||||
|
||||
enum {
|
||||
CREWMATE,
|
||||
IMPOSTER,
|
||||
DIED,
|
||||
COUNT
|
||||
};
|
||||
|
||||
enum {
|
||||
LOBBY,
|
||||
GAME,
|
||||
DISCUSSION
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
char *nick;
|
||||
int num;
|
||||
|
||||
int type;
|
||||
int admin;
|
||||
int map;
|
||||
|
||||
int votes;
|
||||
} CLIENT;
|
||||
|
||||
CLIENT *players;
|
||||
size_t now_players;
|
||||
size_t size_players = 10;
|
||||
|
||||
time_t timer;
|
||||
time_t voting_timer;
|
||||
|
||||
int current_mode;
|
||||
|
||||
int GetByNick(const char *nick, size_t *ret) {
|
||||
for (size_t i = 0; i < now_players; i++)
|
||||
if (!strcmp(nick, players[i].nick)) {
|
||||
*ret = i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void sort(size_t ptr){
|
||||
for (size_t i = ptr; i < now_players; i++)
|
||||
if (i + 1 <= now_players)
|
||||
players[i] = players[i + 1];
|
||||
}
|
||||
|
||||
void clear(void) {
|
||||
for (size_t i = 0; i < size_players; i++)
|
||||
if (players[i].nick)
|
||||
free(players[i].nick);
|
||||
|
||||
memset(players, 0, sizeof(CLIENT) * size_players);
|
||||
|
||||
current_mode = LOBBY;
|
||||
now_players = 0;
|
||||
}
|
||||
|
||||
void broadcast(IRCC_client *irc, const char *ign, const char *msg) {
|
||||
for (size_t i = 0; i < now_players; i++)
|
||||
if (strcmp(ign, players[i].nick))
|
||||
IRCC_send(irc, players[i].nick, msg);
|
||||
}
|
||||
|
||||
int test_player(IRCC_client *irc, const char *nick, size_t *res) {
|
||||
size_t ret = 0;
|
||||
if (GetByNick(nick, &ret)) {
|
||||
IRCC_send(irc, nick, "Firstly join!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
*res = ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void player_quit(IRCC_client *irc, char *buf, size_t size, const char *nick) {
|
||||
size_t ret = 0;
|
||||
if (test_player(irc, nick, &ret))
|
||||
return;
|
||||
|
||||
snprintf(buf, size, "Player [%d] left", players[ret].num);
|
||||
broadcast(irc, nick, buf);
|
||||
|
||||
if (players[ret].admin) {
|
||||
CLIENT *client;
|
||||
if (ret + 1 < now_players)
|
||||
client = &players[ret + 1];
|
||||
|
||||
else
|
||||
client = &players[ret - 1];
|
||||
|
||||
client->admin = 1;
|
||||
|
||||
snprintf(buf, size, "New admin is [%d]", client->num);
|
||||
broadcast(irc, nick, buf);
|
||||
}
|
||||
|
||||
if (players[ret].type == IMPOSTER) {
|
||||
snprintf(buf, size, "[%d] was imposter. Game over!", players[ret].num);
|
||||
broadcast(irc, nick, buf);
|
||||
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
|
||||
free(players[ret].nick);
|
||||
sort(ret);
|
||||
|
||||
now_players--;
|
||||
}
|
||||
|
||||
int gameloop(IRCC_client *irc) {
|
||||
int irc_ret = IRCC_recv(irc);
|
||||
if (irc_ret == IRCC_DISCONNECTED)
|
||||
return 1;
|
||||
|
||||
irc_ret = IRCC_parse(irc);
|
||||
if (irc->irc_msg == NULL || irc->irc_nick == NULL || irc->irc_channel == NULL)
|
||||
return 0;
|
||||
|
||||
/* Common buffer */
|
||||
char buf[512];
|
||||
char *nick = strdup(irc->irc_nick);
|
||||
if (nick == NULL)
|
||||
return 0;
|
||||
|
||||
if (irc_ret == IRCC_PRIVMSG) {
|
||||
if (!strncmp(irc->irc_msg, "!join", 5)) {
|
||||
if (current_mode != LOBBY) {
|
||||
IRCC_send(irc, nick, "Game started");
|
||||
goto END;
|
||||
}
|
||||
|
||||
/* Check player */
|
||||
if (now_players == size_players) {
|
||||
IRCC_send(irc, nick, "Sorry, max players");
|
||||
goto END;
|
||||
}
|
||||
|
||||
size_t ret = 0;
|
||||
if (!GetByNick(nick, &ret)) {
|
||||
IRCC_send(irc, nick, "You already joined");
|
||||
goto END;
|
||||
}
|
||||
|
||||
/* Register */
|
||||
players[now_players].nick = strdup(nick);
|
||||
if (players[now_players].nick == NULL)
|
||||
goto END;
|
||||
|
||||
/* In game nickname */
|
||||
players[now_players].num = rand();
|
||||
|
||||
/* Give admin permission */
|
||||
int admin_flag = 0;
|
||||
if (now_players == 0)
|
||||
admin_flag = 1;
|
||||
|
||||
players[now_players].admin = admin_flag;
|
||||
|
||||
/* Other */
|
||||
players[now_players].map = 0;
|
||||
players[now_players].type = 0;
|
||||
|
||||
/* Inform all */
|
||||
snprintf(buf, sizeof(buf), "New player [%d]! Total: %zu/%zu", players[now_players].num, now_players + 1, size_players);
|
||||
broadcast(irc, nick, buf);
|
||||
|
||||
snprintf(buf, sizeof(buf), "You joined with id [%d]", players[now_players].num);
|
||||
IRCC_send(irc, nick, buf);
|
||||
|
||||
now_players++;
|
||||
}
|
||||
|
||||
else if (!strncmp(irc->irc_msg, "!say", 4)) {
|
||||
if (current_mode == GAME)
|
||||
goto END;
|
||||
|
||||
size_t ret = 0;
|
||||
if (test_player(irc, nick, &ret))
|
||||
goto END;
|
||||
|
||||
if (players[ret].type == DIED) {
|
||||
IRCC_send(irc, nick, "You died! You cant send messages");
|
||||
goto END;
|
||||
}
|
||||
|
||||
snprintf(buf, sizeof(buf), "[%d]:%s", players[ret].num, irc->irc_msg + 4);
|
||||
broadcast(irc, nick, buf);
|
||||
}
|
||||
|
||||
else if (!strncmp(irc->irc_msg, "!exit", 5)) {
|
||||
IRCC_send(irc, nick, "Goodbye!");
|
||||
player_quit(irc, buf, sizeof(buf), nick);
|
||||
}
|
||||
|
||||
else if (!strncmp(irc->irc_msg, "!status", 7)) {
|
||||
size_t ret = 0;
|
||||
if (test_player(irc, nick, &ret))
|
||||
goto END;
|
||||
|
||||
snprintf(buf, sizeof(buf), "Status: Your id [%d] | Players [%zu/%zu]", players[ret].num, now_players, size_players);
|
||||
IRCC_send(irc, nick, buf);
|
||||
}
|
||||
|
||||
else if (!strncmp(irc->irc_msg, "!start", 6)) {
|
||||
if (current_mode != LOBBY) {
|
||||
IRCC_send(irc, nick, "Game already started");
|
||||
goto END;
|
||||
}
|
||||
|
||||
size_t ret = 0;
|
||||
if (GetByNick(nick, &ret)) {
|
||||
IRCC_send(irc, nick, "You are not admin");
|
||||
goto END;
|
||||
}
|
||||
|
||||
current_mode = GAME;
|
||||
timer = time(NULL);
|
||||
|
||||
for (size_t i = 0; i < now_players; i++)
|
||||
players[i].type = CREWMATE;
|
||||
|
||||
size_t im = rand() % now_players;
|
||||
players[im].type = IMPOSTER;
|
||||
|
||||
/* Inform all */
|
||||
broadcast(irc, players[im].nick, "You crewmate");
|
||||
IRCC_send(irc, players[im].nick, "You imposter");
|
||||
}
|
||||
|
||||
else if (!strncmp(irc->irc_msg, "!emergency", 10)) {
|
||||
size_t ret = 0;
|
||||
if (test_player(irc, nick, &ret))
|
||||
goto END;
|
||||
|
||||
current_mode = DISCUSSION;
|
||||
snprintf(buf, sizeof(buf), "Player [%d] pressed emergency button! You have 60 second to vote or skip", players[ret].num);
|
||||
|
||||
voting_timer = time(NULL);
|
||||
}
|
||||
|
||||
else if (!strncmp(irc->irc_msg, "!help", 5))
|
||||
IRCC_send(irc, nick, "[!start] [!help] [!say MSG] [!join] [!exit] [!status] InGame: [!kill] [!go NUM] [!emergency] [!vote NUM] [!skip]");
|
||||
}
|
||||
|
||||
else if (irc_ret == IRCC_QUIT)
|
||||
player_quit(irc, buf, sizeof(buf), nick);
|
||||
|
||||
END:
|
||||
free(nick);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
char *server = "127.0.0.1";
|
||||
char *nick = "amongrass";
|
||||
unsigned int port = 6667;
|
||||
int usessl = 0;
|
||||
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "h:n:p:m:s")) != -1) {
|
||||
switch (opt) {
|
||||
case 'm':
|
||||
sscanf(optarg, "%zu", &size_players);
|
||||
if (size_players < 1 || size_players > 100) {
|
||||
fprintf(stderr, "amongrass: failed to set players count\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
server = optarg;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
port = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
nick = optarg;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
usessl = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("./amongrass [snpm]\n\t-h IP Server ip Default: %s\n\t-n NICK Bot nickname Default: %s\n\t-p PORT Server port Default: %d\n\t-m N Max players in game Default: %zu\n\t-s Use SSL Default: false\n", server, nick, port, size_players);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
players = malloc(sizeof(CLIENT) * size_players);
|
||||
if (players == NULL) {
|
||||
fprintf(stderr, "amongrass: malloc failed: %s", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
IRCC_client irc;
|
||||
if (IRCC_connect(&irc, server, port) == IRCC_ERROR) {
|
||||
fprintf(stderr, "amongrass: failed connect to %s: %s\n", server, strerror(errno));
|
||||
goto EXIT_MAIN;
|
||||
}
|
||||
|
||||
if (usessl) {
|
||||
#ifdef ENABLE_SSL
|
||||
if (IRCC_initssl(&irc) == IRCC_ERROR) {
|
||||
fprintf(stderr, "amongrass: irc_ssl: %s\n", ERR_error_string(ERR_get_error(), NULL));
|
||||
goto EXIT_MAIN;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (IRCC_register(&irc, nick) == IRCC_DISCONNECTED) {
|
||||
fprintf(stderr, "amongrass: irc: disconnected\n");
|
||||
goto EXIT_MAIN;
|
||||
}
|
||||
|
||||
timer = time(NULL);
|
||||
current_mode = LOBBY;
|
||||
srand(getpid());
|
||||
|
||||
fprintf(stderr, "amongrass: Successful connected\namongrass: Nickname: %s\n", nick);
|
||||
|
||||
while (1) {
|
||||
if (time(NULL) - timer >= 60) {
|
||||
broadcast(&irc, "", "Time is over!");
|
||||
clear();
|
||||
}
|
||||
|
||||
if (gameloop(&irc))
|
||||
break;
|
||||
}
|
||||
|
||||
IRCC_close(&irc);
|
||||
for (size_t i = 0; i < size_players; i++)
|
||||
if (players[i].nick)
|
||||
free(players[i].nick);
|
||||
|
||||
EXIT_MAIN:
|
||||
free(players);
|
||||
return 1;
|
||||
}
|
Loading…
Reference in New Issue
Block a user