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