#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <ctype.h>
// GAME STATS CONSTANTS
#define MIN_HP 20
#define MAX_HP 30
#define MIN_PM 1
#define MAX_PM 3
#define MIN_DMG 2
#define MAX_DMG 6
#ifndef PORT
#define PORT 52934
#endif
#define SECONDS 10
#define MAX_NAME 20
#define MAX_SPEAK 256
// linked list
struct client {
int fd;
struct in_addr ipaddr;
struct client *next;
struct client *matched; // pointer to another client that this client most recently matched with
char name[MAX_NAME];
int hp; // 20-30
int pm; // 50% to hit; 3x dmg
int in_match;
int shield;
int shielded;
int health_potion;
};
static struct client *addclient(struct client *top, int fd, struct in_addr addr, char name[MAX_NAME]);
static struct client *removeclient(struct client *top, int fd);
static void broadcast(struct client *top, char *s, int size);
static struct client **matchclient(struct client *head);
int handleclient(struct client *p, struct client *top);
static struct client *moveclienttoend(struct client **top, int fd);
static void roundstartroutine(struct client *player, struct client *opponent);
static void commandmenuroutine(struct client *active_player);
char *process_move(struct client *player);
int bindandlisten(void);
int main() {
int clientfd, maxfd, nready;
struct client *p;
struct client *head = NULL;
socklen_t len;
struct sockaddr_in q;
struct timeval tv;
fd_set allset;
fd_set rset;
int i;
time_t t;
// using srand() for randomization
srand((unsigned) time(&t));
// creates the socket, binds and listens as the server socket should do
int listenfd = bindandlisten();
// initialize allset and add listenfd to the
// set of file descriptors passed into select
FD_ZERO(&allset);
FD_SET(listenfd, &allset);
// we want to know the max file descriptor number for use in select()
maxfd = listenfd;
while (1) {
// make a copy of the set before we pass it into select
rset = allset;
// timeout
tv.tv_sec = SECONDS;
tv.tv_usec = 0; /* and microseconds */
nready = select(maxfd + 1, &rset, NULL, NULL, &tv);
if (nready == 0) {
printf("No response from clients in %d seconds\n", SECONDS);
continue;
}
if (nready == -1) {
perror("select");
continue;
}
// does accept sys call as a server socket should do
if (FD_ISSET(listenfd, &rset)) {
printf("a new client is connecting\n");
len = sizeof(q);
// clientfd is the file descriptor representing the client socket connected to
if ((clientfd = accept(listenfd, (struct sockaddr *)&q, &len)) < 0) {
perror("accept");
exit(1);
}
// adds clientfd to the allset file descriptor set
FD_SET(clientfd, &allset);
if (clientfd > maxfd) {
maxfd = clientfd;
}
printf("connection from %s\n", inet_ntoa(q.sin_addr));
#pragma region ASK NEW CLIENT FOR NAME
char input_name[MAX_NAME];
char big_name[MAX_SPEAK];
char *join_msg = "What is your name?";
write(clientfd, join_msg, strlen(join_msg));
int num_chars = read(clientfd, big_name, MAX_SPEAK);
input_name[num_chars] = '\0';
while (strstr(big_name, "\r\n") == NULL) {
num_chars += read(clientfd, &big_name[num_chars], MAX_SPEAK - num_chars);
big_name[num_chars] = '\0';
}
big_name[num_chars - 2] = '\0';
memcpy(input_name, big_name, MAX_NAME - 1);
#pragma endregion
// copy of all clients before adding new one
struct client *head_copy = head;
// head is the previous head of the linked list we can traverse through, returns newest head
head = addclient(head, clientfd, q.sin_addr, input_name);
#pragma region SEND MESSAGE TO CLIENT WHEN NAME IS GIVEN
char success_msg[MAX_SPEAK];
sprintf(success_msg, "Welcome, %s! Awaiting opponent...\r\n", input_name);
write(clientfd, success_msg, strlen(success_msg));
#pragma endregion
#pragma region SEND LOGIN MESSAGE TO ALL OTHER CLIENTS
if (head_copy == NULL) { // head doesn't have anything prior to first client
continue;
}
// traversing linked list to send message to all clients excluding recent login
else if (head_copy->fd != head->fd) {
while (head_copy != NULL) {
char all_join_msg[MAX_SPEAK];
sprintf(all_join_msg, "**%s enters the arena**\r\n", input_name);
write(head_copy->fd, all_join_msg, strlen(all_join_msg));
head_copy = head_copy->next;
}
}
}
#pragma endregion
/* find two clients that can be matched to each other, otherwise if there are no
* suitable players, the pointers are null */
struct client **matchingClients = matchclient(head);
// main single-match logic
if (matchingClients[0] != NULL && matchingClients[1] != NULL) {
#pragma region PRINT ENGAGE MESSAGE TO MATCHED CLIENTS
// these clients are now matched with each other
matchingClients[0]->matched = matchingClients[1];
matchingClients[1]->matched = matchingClients[0];
matchingClients[0]->in_match = 1;
matchingClients[1]->in_match = 1;
char engage1[MAX_SPEAK];
sprintf(engage1, "You engage %s!\r\n", matchingClients[0]->name);
write(matchingClients[1]->fd, engage1, strlen(engage1));
char engage2[MAX_SPEAK];
sprintf(engage2, "You engage %s!\r\n", matchingClients[1]->name);
write(matchingClients[0]->fd, engage2, strlen(engage2));
#pragma endregion
#pragma region USE RAND() TO DECIDE PLAYER HP, POWERMOVES, FIRST ACTIVE PLAYER, SHIELD, HEALTH
int hp_player_1 = rand() % 11 + MIN_HP;
int hp_player_2 = rand() % 11 + MIN_HP;
matchingClients[0]->hp = hp_player_1;
matchingClients[1]->hp = hp_player_2;
int pm_player_1 = rand() % 3 + MIN_PM;
int pm_player_2 = rand() % 3 + MIN_PM;
matchingClients[0]->pm = pm_player_1;
matchingClients[1]->pm = pm_player_2;
int shield_player_1 = rand() % 3 + MIN_PM;
int shield_player_2 = rand() % 3 + MIN_PM;
matchingClients[0]->shield = shield_player_1;
matchingClients[1]->shield = shield_player_2;
int health_player_1 = rand() % 3 + MIN_PM;
int health_player_2 = rand() % 3 + MIN_PM;
matchingClients[0]->health_potion = health_player_1;
matchingClients[1]->health_potion = health_player_2;
matchingClients[0] ->shielded = 0;
matchingClients[1] ->shielded = 0;
int choose_active_player = rand() % 2;
// active_player stores the fd of the current attacking player, which starts randomized
int active_player;
if (choose_active_player == 0) {
active_player = matchingClients[0]->fd;
} else {
active_player = matchingClients[1]->fd;
}
#pragma endregion
#pragma region ACTUAL GAME LOGIC
// stores info about client drops before the client can be removed from linked list
int p0_drop = 0;
char p0_name[MAX_NAME];
strncpy(p0_name, matchingClients[0]->name, MAX_NAME);
int p1_drop = 0;
char p1_name[MAX_NAME];
strncpy(p1_name, matchingClients[1]->name, MAX_NAME);
// while both players are alive
while ( (matchingClients[0]->hp > 0) && (matchingClients[1]->hp > 0) ) {
// prints round start player info to a player; hp, pms, shields, heals and opponent hp
roundstartroutine(matchingClients[0], matchingClients[1]);
roundstartroutine(matchingClients[1], matchingClients[0]);
// logic for the current attacking player
if (active_player == matchingClients[0]->fd) {
char strike_wait[MAX_SPEAK];
sprintf(strike_wait, "Waiting for %s to strike...\r\n", matchingClients[0]->name);
write(matchingClients[1]->fd, strike_wait, strlen(strike_wait));
// prints a menu of valid commands that the active player can make
commandmenuroutine(matchingClients[0]);
// processes the move that the active player makes
char *result = process_move(matchingClients[0]);
// if client has dropped
if ( (strcmp(result, "d") == 0) ) {
p0_drop = 1;
int tmp_fd = matchingClients[0]->fd;
head = removeclient(head, matchingClients[0]->fd);
FD_CLR(tmp_fd, &allset);
close(tmp_fd);
break;
}
// if player gave an invalid move 'f' or chose to speak/shield do not end round
while ( (strcmp(result, "f") == 0) || (strcmp(result, "s") == 0) || (strcmp(result, "x") == 0) ) {
// if they spoke or shielded we need to print routines again
if ( (strcmp(result, "s") == 0) || (strcmp(result, "x") == 0) ) {
roundstartroutine(matchingClients[0], matchingClients[1]);
roundstartroutine(matchingClients[1], matchingClients[0]);
write(matchingClients[1]->fd, strike_wait, strlen(strike_wait));
commandmenuroutine(matchingClients[0]);
}
result = process_move(matchingClients[0]);
}
// switch the active player for next round
active_player = matchingClients[1]->fd;
// repeat code for current attacking player
} else {
char strike_wait[MAX_SPEAK];
sprintf(strike_wait, "Waiting for %s to strike...\r\n", matchingClients[1]->name);
write(matchingClients[0]->fd, strike_wait, strlen(strike_wait));
// prints a menu of valid commands that the active player can make
commandmenuroutine(matchingClients[1]);
// processes the move that the active player makes
char *result = process_move(matchingClients[1]);
// if client has dropped
if ( (strcmp(result, "d") == 0) ) {
p1_drop = 1;
int tmp_fd = matchingClients[1]->fd;
head = removeclient(head, matchingClients[1]->fd);
FD_CLR(tmp_fd, &allset);
close(tmp_fd);
break;
}
// if player gave an invalid move 'f' or chose to speak/shield do not end round
while ( (strcmp(result, "f") == 0) || (strcmp(result, "s") == 0) || (strcmp(result, "x") == 0) ) {
// if they spoke or shielded we need to print routines again
if ( (strcmp(result, "s") == 0) || (strcmp(result, "x") == 0) ) {
roundstartroutine(matchingClients[1], matchingClients[0]);
roundstartroutine(matchingClients[0], matchingClients[1]);
write(matchingClients[0]->fd, strike_wait, strlen(strike_wait));
commandmenuroutine(matchingClients[1]);
}
result = process_move(matchingClients[1]);
}
// switch the active player for next round
active_player = matchingClients[0]->fd;
}
}
#pragma endregion
#pragma region A PLAYER HAS WON
if ( (matchingClients[0]->hp > 0) && p0_drop == 0 && p1_drop == 0) {
char victory[MAX_SPEAK];
sprintf(victory, "%s gives up. You win!\r\n\n", matchingClients[1]->name);
write(matchingClients[0]->fd, victory, strlen(victory));
char loss[MAX_SPEAK];
sprintf(loss, "You are no match for %s. You scurry away...\r\n\n", matchingClients[0]->name);
write(matchingClients[1]->fd, loss, strlen(loss));
char awaiting[MAX_SPEAK];
sprintf(awaiting, "Awaiting next opponent...\r\n");
write(matchingClients[0]->fd, awaiting, strlen(awaiting));
write(matchingClients[1]->fd, awaiting, strlen(awaiting));
// both players no longer in a match
matchingClients[0]->in_match = 0;
matchingClients[1]->in_match = 0;
// move both clients to end of linked list, rematching preference given to winner
head = moveclienttoend(&head, matchingClients[0]->fd);
head = moveclienttoend(&head, matchingClients[1]->fd);
} else if ( (matchingClients[1]->hp > 0) && p0_drop == 0 && p1_drop == 0) {
char victory[MAX_SPEAK];
sprintf(victory, "%s gives up. You win!\r\n\n", matchingClients[0]->name);
write(matchingClients[1]->fd, victory, strlen(victory));
char loss[MAX_SPEAK];
sprintf(loss, "You are no match for %s. You scurry away...\r\n\n", matchingClients[1]->name);
write(matchingClients[0]->fd, loss, strlen(loss));
char awaiting[MAX_SPEAK];
sprintf(awaiting, "Awaiting next opponent...\r\n");
write(matchingClients[0]->fd, awaiting, strlen(awaiting));
write(matchingClients[1]->fd, awaiting, strlen(awaiting));
// both players no longer in a match
matchingClients[0]->in_match = 0;
matchingClients[1]->in_match = 0;
// move both clients to end of linked list, rematching preference given to winner
head = moveclienttoend(&head, matchingClients[1]->fd);
head = moveclienttoend(&head, matchingClients[0]->fd);
} else {
// if one of the clients has dropped, game ended unnaturally
if (p0_drop == 1) {
char dropped[MAX_SPEAK];
sprintf(dropped, "\n--%s dropped. You win!\r\n\n", p0_name);
write(matchingClients[1]->fd, dropped, strlen(dropped));
char awaiting[MAX_SPEAK];
sprintf(awaiting, "Awaiting next opponent...\r\n");
write(matchingClients[1]->fd, awaiting, strlen(awaiting));
// broadcast to all players that player dropped
char outbuf[512];
printf("Disconnect from %s\n", p0_name);
sprintf(outbuf, "**%s leaves**\r\n", p0_name);
broadcast(head, outbuf, strlen(outbuf));
} else if (p1_drop == 1) {
char dropped[MAX_SPEAK];
sprintf(dropped, "\n--%s dropped. You win!\r\n\n", p1_name);
write(matchingClients[0]->fd, dropped, strlen(dropped));
char awaiting[MAX_SPEAK];
sprintf(awaiting, "Awaiting next opponent...\r\n");
write(matchingClients[0]->fd, awaiting, strlen(awaiting));
// broadcast to all players that player dropped
char outbuf[512];
printf("Disconnect from %s\n", p1_name);
sprintf(outbuf, "**%s leaves**\r\n", p1_name);
broadcast(head, outbuf, strlen(outbuf));
}
}
#pragma endregion
} else {
continue;
}
for (i = 0; i <= maxfd; i++) {
// if the fd is one of all the file descriptors we've encountered so far
if (FD_ISSET(i, &rset)) {
// traverse the linked list
for (p = head; p != NULL; p = p->next) {
// if fd in the linked list is the same as i
if (p->fd == i) {
// read from the client socket, broadcast messages to all clients
int result = handleclient(p, head);
if (result == -1) {
int tmp_fd = p->fd;
head = removeclient(head, p->fd);
FD_CLR(tmp_fd, &allset);
close(tmp_fd);
}
break;
}
}
}
}
}
return 0;
}
int handleclient(struct client *p, struct client *top) {
char buf[256];
char outbuf[512];
int len = read(p->fd, buf, sizeof(buf) - 1);
if (len > 0) {
buf[len] = '\0';
printf("Received %d bytes: %s", len, buf);
sprintf(outbuf, "%s says: %s", inet_ntoa(p->ipaddr), buf);
broadcast(top, outbuf, strlen(outbuf));
return 0;
} else if (len <= 0) {
// socket is closed
printf("Disconnect from %s\n", inet_ntoa(p->ipaddr));
sprintf(outbuf, "Goodbye %s\r\n", inet_ntoa(p->ipaddr));
broadcast(top, outbuf, strlen(outbuf));
return -1;
}
return -1;
}
/* bind and listen, abort on error
* returns FD of listening socket
*/
int bindandlisten(void) {
struct sockaddr_in r;
int listenfd;
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
exit(1);
}
int yes = 1;
if ((setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int))) == -1) {
perror("setsockopt");
}
memset(&r, '\0', sizeof(r));
r.sin_family = AF_INET;
r.sin_addr.s_addr = INADDR_ANY;
r.sin_port = htons(PORT);
if (bind(listenfd, (struct sockaddr *)&r, sizeof r)) {
perror("bind");
exit(1);
}
if (listen(listenfd, 5)) {
perror("listen");
exit(1);
}
return listenfd;
}
static struct client *addclient(struct client *top, int fd, struct in_addr addr, char name[MAX_NAME]) {
struct client *p = malloc(sizeof(struct client));
if (!p) {
perror("malloc");
exit(1);
}
printf("Adding client %s\n", inet_ntoa(addr));
p->fd = fd;
p->ipaddr = addr;
p->next = top;
strncpy(p->name, name, MAX_NAME);
top = p;
return top;
}
static struct client *removeclient(struct client *top, int fd) {
struct client **p;
for (p = ⊤ *p && (*p)->fd != fd; p = &(*p)->next)
;
// Now, p points to (1) top, or (2) a pointer to another client
// This avoids a special case for removing the head of the list
if (*p) {
struct client *t = (*p)->next;
printf("Removing client %d %s\n", fd, inet_ntoa((*p)->ipaddr));
free(*p);
*p = t;
} else {
fprintf(stderr, "Trying to remove fd %d, but I don't know about it\n",
fd);
}
return top;
}
// returns head of linked list
static struct client *moveclienttoend(struct client **top, int fd) {
struct client *prev = NULL;
struct client *current = *top;
// traverse to find pos of client with given fd
while (current != NULL && current->fd != fd) {
prev = current;
current = current->next;
}
// if client not found or client is already at the end, do nothing
if (current == NULL || current->next == NULL) {
return *top;
}
// detach client from its current position
if (prev != NULL) {
prev->next = current->next;
} else {
*top = current->next;
}
// traverse to end of the list
struct client *last = *top;
while (last->next != NULL) {
last = last->next;
}
// attach the target client to the end of the list
last->next = current;
current->next = NULL;
return *top;
}
struct client **matchclient(struct client *head) {
struct client *first = NULL, *second = NULL; //initialize two players
struct client *current = head;
// struct client *temp = NULL;
while (current != NULL) {
//find the first client that is not in an active match
if (!current->in_match) {
first = current;
break; // Found first
}
current = current->next;
}
current = first;
while (current != NULL){
if ( (!current->in_match) && (current->matched != first) && (current->fd != first->fd) ){
second = current;
break; //Found opponent for first
}
current = current->next;
}
// Allocate memory for the array of pointers to clients
struct client** matched_players = malloc(2 * sizeof(struct client));
if (matched_players != NULL) {
matched_players[0] = first;
matched_players[1] = second;
}
return matched_players;
}
// prints round start player info to a player; hp, pms, shields, heals and opponent hp
static void roundstartroutine(struct client *player, struct client *opponent) {
char hitpoints[MAX_SPEAK];
sprintf(hitpoints, "Your hitpoints: %i\r\n", player->hp);
write(player->fd, hitpoints, strlen(hitpoints));
char power_moves[MAX_SPEAK];
sprintf(power_moves, "Your powermoves: %i\r\n\n", player->pm);
write(player->fd, power_moves, strlen(power_moves));
char shields[MAX_SPEAK];
sprintf(shields, "Your shields: %i\r\n\n", player->shield);
write(player->fd, shields, strlen(shields));
char health[MAX_SPEAK];
sprintf(health, "Your health potions: %i\r\n\n", player->health_potion);
write(player->fd, health, strlen(health));
char opp_hitpoints[MAX_SPEAK];
sprintf(opp_hitpoints, "%s's hitpoints: %i\r\n", opponent->name, opponent->hp);
write(player->fd, opp_hitpoints, strlen(opp_hitpoints));
}
static void commandmenuroutine(struct client *active_player) {
char *newline = "\r\n";
write(active_player->fd, newline, strlen(newline));
char *attack = "(a)ttack\r\n";
write(active_player->fd, attack, strlen(attack));
if (active_player->pm > 0) {
char *powermoves = "(p)owermove\r\n";
write(active_player->fd, powermoves, strlen(powermoves));
}
char *speak = "(s)peak something\r\n";
write(active_player->fd, speak, strlen(speak));
if (active_player->shield > 0 && active_player->shielded == 0) {
char *shields = "(x)shield\r\n";
write(active_player->fd, shields, strlen(shields));
}
if (active_player->health_potion > 0) {
char *health = "(h)ealth pot\r\n";
write(active_player->fd, health, strlen(health));
}
}
char *process_move(struct client *player) {
struct client *opponent = player->matched;
int socket = player->fd;
// read command
char move[MAX_SPEAK];
int num_chars = read(socket, move, MAX_SPEAK);
if (num_chars <= 0) {
// socket is closed, client dropped
return "d";
}
move[num_chars] = '\0';
// converts the move char to lowercase if it was given uppercase
for (int i = 0; move[i] != '\0'; i++) {
move[i] = tolower(move[i]);
}
// add a check to not even run the p command if the active player doesnt have pm > 0
if (strcmp(move, "p") == 0 && (player->pm > 0) ){
//50% chance to hit the power move
int random_number = (rand() % 2) + 1;
//power move hit
if (random_number == 1 && player->pm >= 1){
if (opponent->shielded == 0) {
player->pm -= 1;
// int damage = (player->dmg * player->pm);
int damage = 3 * ((rand() % 5) + MIN_DMG);
opponent->hp = opponent->hp - damage;
//write that power move hit
char powerhit[MAX_SPEAK];
sprintf(powerhit, "\nYou hit %s for %i damage!\r\n", opponent->name, damage);
write(socket, powerhit, strlen(powerhit));
//write that power move hit opponent
char powerhit2[MAX_SPEAK];
sprintf(powerhit2, "\n%s powermoves you for %i damage!\r\n", player->name, damage);
write(opponent->fd, powerhit2, strlen(powerhit2));
} else {
//write that player attack got blocked
char attackmiss[MAX_SPEAK];
sprintf(attackmiss, "\n%s used a shield and negated the damage!\r\n", opponent->name);
write(socket, attackmiss, strlen(attackmiss));
//write to opponent player attacked and did no damage
char attackmiss2[MAX_SPEAK];
sprintf(attackmiss2, "\n%s powermoves you but you block all damage!\r\n", player->name);
write(opponent->fd, attackmiss2, strlen(attackmiss2));
opponent->shielded = 0;
}
} else {
//write that the power move failed
player->pm -= 1;
char powerfail[MAX_SPEAK];
sprintf(powerfail, "\nYou missed!\r\n");
write(socket, powerfail, strlen(powerfail));
char powerfail2[MAX_SPEAK];
sprintf(powerfail2, "%s missed you!\r\n", player->name);
write(opponent->fd, powerfail2, strlen(powerfail2));
}
return "p";
}
else if (strcmp(move, "s") == 0) {
char *smsg = "\n\nSpeak: ";
write(socket, smsg, strlen(smsg));
//take player message
char msg[MAX_SPEAK - 60];
char big_msg[4 * MAX_SPEAK];
int num_chars = read(socket, big_msg, 4 * MAX_SPEAK);
if (num_chars <= 0) {
// socket is closed, client dropped
return "d";
}
big_msg[num_chars] = '\0';
// it may take more than one read to get all of the data that was written
while(strstr(big_msg, "\r\n") == NULL) {
num_chars += read(socket, &big_msg[num_chars], (4 * MAX_SPEAK)-num_chars);
big_msg[num_chars]='\0';
}
big_msg[num_chars-2] = '\0';
memcpy(msg, big_msg, MAX_SPEAK - 60);
char msg2[MAX_SPEAK];
sprintf(msg2, "You speak: %s\r\n\n", msg);
write(socket, msg2, strlen(msg2));
//send message to opponent
char msg3[MAX_SPEAK];
sprintf(msg3, "%s takes a break to tell you:\n%s\r\n\n", player->name, msg);
write(opponent->fd, msg3, strlen(msg3));
return "s";
} else if (strcmp(move, "a") == 0){
if (opponent->shielded == 0) {
int damage = (rand() % 5) + MIN_DMG;
opponent->hp = opponent->hp - damage;
//write that player attacked opponent
char attackhit[MAX_SPEAK];
sprintf(attackhit, "\nYou hit %s for %i damage!\r\n", opponent->name, damage);
write(socket, attackhit, strlen(attackhit));
//write to opponent player attacked
char attackhit2[MAX_SPEAK];
sprintf(attackhit2, "\n%s hits you for %i damage!\r\n", player->name, damage);
write(opponent->fd, attackhit2, strlen(attackhit2));
} else {
//write that player attack got blocked
char attackmiss[MAX_SPEAK];
sprintf(attackmiss, "\n%s used a shield and negated the damage!\r\n", opponent->name);
write(socket, attackmiss, strlen(attackmiss));
//write to opponent player attacked and did no damage
char attackmiss2[MAX_SPEAK];
sprintf(attackmiss2, "\n%s hits you but you block all damage!\r\n", player->name);
write(opponent->fd, attackmiss2, strlen(attackmiss2));
opponent->shielded = 0;
}
return "a";
} else if (strcmp(move, "x") == 0 && player->shield > 0 && player->shielded == 0) {
player->shield -= 1;
player->shielded = 1;
char *xmsg = "\n\nShield has been activated.\n";
write(socket, xmsg, strlen(xmsg));
return "x";
} else if (strcmp(move, "h") == 0 && player-> health_potion > 0) {
player->health_potion -= 1;
int hp = (rand() % 5) + MIN_DMG;
player->hp += hp;
char healmsg[MAX_SPEAK];
sprintf(healmsg, "\nYou healed for %i hp!\r\n", hp);
write(player->fd, healmsg, strlen(healmsg));
char healmsg2[MAX_SPEAK];
sprintf(healmsg2, "\n%s healed for %i hp!\r\n", player->name, hp);
write(opponent->fd, healmsg2, strlen(healmsg2));
return "h";
} else {
// player inputted invalid move
return "f";
}
}
static void broadcast(struct client *top, char *s, int size) {
struct client *p;
for (p = top; p; p = p->next) {
write(p->fd, s, size);
}
/* should probably check write() return value and perhaps remove client */
}
// finished