2016-09-20 21:00:21 +00:00
|
|
|
// Ben Harris
|
|
|
|
|
|
|
|
// Multiplayer command-line shooter server
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
#include <fstream>
|
|
|
|
#include <sstream>
|
|
|
|
#include <cstdlib>
|
|
|
|
#include <string>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/wait.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <netdb.h>
|
|
|
|
#include <fdstream/fdstream.h>
|
|
|
|
#include <poll.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include "server.h"
|
2022-01-16 04:52:50 +00:00
|
|
|
|
2016-09-20 21:00:21 +00:00
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
ppos pos[26];
|
|
|
|
Board board;
|
|
|
|
struct pollfd fds[26];
|
|
|
|
|
2022-01-16 04:52:50 +00:00
|
|
|
int main(int argc, char **argv) {
|
|
|
|
for (int r = 1; r < 26; r++) fds[r].fd = -1;
|
|
|
|
fds[0].fd = socket(AF_INET, SOCK_STREAM, 0);
|
|
|
|
sockaddr_in sin;
|
|
|
|
sin.sin_family = AF_INET;
|
|
|
|
sin.sin_port = htons(12421);
|
|
|
|
sin.sin_addr.s_addr = INADDR_ANY;
|
|
|
|
int b = bind(fds[0].fd, (sockaddr * ) & sin, sizeof(sockaddr_in));
|
|
|
|
if (b < 0) {
|
|
|
|
perror("bind");
|
|
|
|
exit(1);
|
2016-09-20 21:00:21 +00:00
|
|
|
}
|
2022-01-16 04:52:50 +00:00
|
|
|
fds[0].events = POLLIN;
|
|
|
|
listen(fds[0].fd, 26);
|
|
|
|
string line;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
if (poll(fds, 26, -1) < 0) {
|
|
|
|
perror("poll");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
if (fds[0].revents & POLLIN) {
|
|
|
|
int f = 1;
|
|
|
|
for (; f <= 25; f++) if (fds[f].fd == -1) break;
|
|
|
|
new_player(f);
|
|
|
|
}
|
|
|
|
for (int i = 1; i <= 25; i++) {
|
|
|
|
if (fds[i].revents & POLLIN && fds[i].fd != -1) {
|
|
|
|
if (getline(pos[i].read, line)) {
|
|
|
|
do_line(line, i);
|
|
|
|
} else {
|
|
|
|
ostringstream msg;
|
|
|
|
msg << "Player " << i << "'s client disconnected";
|
|
|
|
kill_player(i);
|
|
|
|
alert(msg.str());
|
|
|
|
}
|
|
|
|
update();
|
|
|
|
}
|
2016-09-20 21:00:21 +00:00
|
|
|
}
|
|
|
|
}
|
2022-01-16 04:52:50 +00:00
|
|
|
return 0;
|
2016-09-20 21:00:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// METHODS ////////////////////////////////////////////////////////////////////
|
2022-01-16 04:52:50 +00:00
|
|
|
void do_line(string line, int player) {
|
|
|
|
if (line == "MOVE") { pos[player].move_forward(); }
|
|
|
|
else if (line == "LEFT") { pos[player].turn_left(); }
|
|
|
|
else if (line == "RIGHT") { pos[player].turn_right(); }
|
|
|
|
else if (line == "FIRE") { shoot(player); }
|
|
|
|
else if (line == "SCAN") { scan(player); }
|
|
|
|
else if (line == "EXIT") {
|
|
|
|
kill_player(player);
|
|
|
|
ostringstream msg;
|
|
|
|
msg << "Player " << player << " threw in the towel";
|
|
|
|
alert(msg.str());
|
|
|
|
} else if (line == "HELP" || line == "help") {
|
|
|
|
pos[player].write
|
|
|
|
<< "Commands are: MOVE, LEFT, RIGHT, SCAN, FIRE, and EXIT. Kill other players. Join and leave at any time."
|
|
|
|
<< endl;
|
|
|
|
} else { pos[player].write << "invalid command. type HELP for more info." << endl; }
|
|
|
|
// cout << "Player " << player << " at (" << pos[player].row << ", " << pos[player].col << ") facing " << pos[player].dr << "dr and " << pos[player].dc << "dc" <<endl;
|
2016-09-20 21:00:21 +00:00
|
|
|
}
|
|
|
|
|
2022-01-16 04:52:50 +00:00
|
|
|
void new_player(int player) {
|
|
|
|
if (player > 25) return;
|
|
|
|
srand(time(NULL));
|
|
|
|
ostringstream msg; // need ostringstream to concatenate int with strings
|
|
|
|
msg << "Player " << player << " joined the game";
|
|
|
|
alert(msg.str());
|
|
|
|
fds[player].fd = accept(fds[0].fd, NULL, NULL);
|
|
|
|
int i = rand() % 10, j = rand() % 10;
|
|
|
|
while (board[i][j]) {
|
|
|
|
i = rand() % 10;
|
|
|
|
j = rand() % 10;
|
|
|
|
}
|
|
|
|
pos[player].row = i;
|
|
|
|
pos[player].col = j;
|
|
|
|
pos[player].dr = rand() % 3 - 1;
|
|
|
|
pos[player].dc = pos[player].dr == 0 ? rand() % 2 ? 1 : -1 : 0;
|
|
|
|
fds[player].events = POLLIN;
|
|
|
|
fds[player].revents = 0;
|
|
|
|
pos[player].read.clear();
|
|
|
|
pos[player].read.attach(fds[player].fd);
|
|
|
|
pos[player].write.clear();
|
|
|
|
pos[player].write.attach(fds[player].fd);
|
|
|
|
pos[player].write << "You are player " << player << endl;
|
|
|
|
update();
|
2016-09-20 21:00:21 +00:00
|
|
|
}
|
|
|
|
|
2022-01-16 04:52:50 +00:00
|
|
|
void kill_player(int player) {
|
|
|
|
pos[player].read.close();
|
|
|
|
pos[player].write.close();
|
|
|
|
fds[player].events = 0;
|
|
|
|
fds[player].revents = 0;
|
|
|
|
fds[player].fd = -1;
|
2016-09-20 21:00:21 +00:00
|
|
|
}
|
|
|
|
|
2022-01-16 04:52:50 +00:00
|
|
|
void alert(string msg) {
|
|
|
|
for (int i = 1; i <= 25; i++) if (fds[i].fd != -1) pos[i].write << msg << endl;
|
2016-09-20 21:00:21 +00:00
|
|
|
}
|
|
|
|
|
2022-01-16 04:52:50 +00:00
|
|
|
void shoot(int player) {
|
|
|
|
update();
|
|
|
|
int curr;
|
|
|
|
for (int i = 1; i <= 5; i++) {
|
|
|
|
curr = board[(pos[player].row + i * pos[player].dr + 10) % 10][(pos[player].col + i * pos[player].dc + 10) %
|
|
|
|
10];
|
|
|
|
if (curr == 0) continue;
|
|
|
|
else {
|
|
|
|
pos[player].write << "You shot player " << curr << endl;
|
|
|
|
pos[curr].write << "You were shot by player " << player << endl;
|
|
|
|
ostringstream msg;
|
|
|
|
msg << "Player " << player << " shot " << curr;
|
|
|
|
kill_player(curr);
|
|
|
|
alert(msg.str());
|
|
|
|
break;
|
|
|
|
}
|
2016-09-20 21:00:21 +00:00
|
|
|
}
|
2022-01-16 04:52:50 +00:00
|
|
|
update();
|
2016-09-20 21:00:21 +00:00
|
|
|
}
|
|
|
|
|
2022-01-16 04:52:50 +00:00
|
|
|
void update() {
|
|
|
|
for (int i = 0; i < 10; i++) for (int j = 0; j < 10; j++) board[i][j] = 0;
|
|
|
|
for (int i = 1; i <= 25; i++) {
|
|
|
|
if (fds[i].fd == -1) continue;
|
|
|
|
if (!board[pos[i].row][pos[i].col]) {
|
|
|
|
board[pos[i].row][pos[i].col] = i;
|
|
|
|
} else {
|
|
|
|
int other_player = board[pos[i].row][pos[i].col];
|
|
|
|
ostringstream msg;
|
|
|
|
msg << "Players " << i << " and " << other_player << " died in a collision";
|
|
|
|
pos[i].write << "You died in a collision with player " << other_player << endl;
|
|
|
|
kill_player(i);
|
|
|
|
pos[other_player].write << "You died in a collision with player " << i << endl;
|
|
|
|
kill_player(other_player);
|
|
|
|
alert(msg.str());
|
|
|
|
}
|
2016-09-20 21:00:21 +00:00
|
|
|
}
|
2022-01-16 04:52:50 +00:00
|
|
|
// for(int i = 0 ; i < 10; i++){ // debug
|
|
|
|
// for(int j = 0; j < 10; j++)
|
|
|
|
// cout << board[i][j] << " ";
|
|
|
|
// cout << endl;
|
|
|
|
// }
|
2016-09-20 21:00:21 +00:00
|
|
|
}
|
|
|
|
|
2022-01-16 04:52:50 +00:00
|
|
|
void scan(int player) {
|
|
|
|
update();
|
|
|
|
pos[player].write << "printscan" << endl;
|
|
|
|
for (int i = 5; i >= 1; i--) {
|
|
|
|
for (int j = 2; j >= -2; j--)
|
|
|
|
pos[player].write << board[(pos[player].row - j * pos[player].dc + i * pos[player].dr + 10) % 10][
|
|
|
|
(pos[player].col + i * pos[player].dc + j * pos[player].dr + 10) % 10] << " ";
|
|
|
|
pos[player].write << "\n_ _ _ _ _\n";
|
|
|
|
}
|
|
|
|
pos[player].write.flush();
|
2016-09-20 21:00:21 +00:00
|
|
|
}
|