/*
* Copyright (C) 2021 Thomas Van Acker
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see .
*
* This project is hosted on https://git.bitscuit.be/bitscuit/BoxEscape
*
*/
// Imports
const http = require("http");
const url = require("url");
const fs = require("fs");
const util = require("util");
// Vars
const hostname = "192.168.0.128";
const port = 3000;
const STATE_LOBBY = 0;
const STATE_GAME = 1;
var state = STATE_LOBBY;
var userSockets = [];
var userNames = [];
var userOK = [];
const BOX_TYPE_TIP = 0;
const BOX_TYPE_KEY = 1;
const BOX_TYPE_BOMB = 2;
var boxes = []; // 2D array with box objects
var currentUserID = -1;
var guardID = 0;
// Create HTTP server
const server = http.createServer((req, res) => {
// Parse url
const requrl = url.parse(req.url);
var reqpath = requrl.pathname;
if(reqpath == "/") reqpath = "/index.html";
// Respond to requests
try{
// Return requested page
res.statusCode = 200;
res.write(fs.readFileSync("html"+reqpath));
res.end();
}catch(error){
// 404 if page not found
res.statusCode = 404;
res.setHeader("Content-Type", "text/plain");
res.end("404 - Page Not Found");
}
});
// Create socket.io server
const io = require("socket.io")(server); // Can only be done when server is created
io.on("connection", (socket) => {
console.log("New user connected!");
// Init socket listeners
// Disconnect
socket.on("disconnect", () => {
console.log("User disconnected!");
// Remove from user lists
if(userSockets.indexOf(socket) != -1){
// When in users list
name = userNames[userSockets.indexOf(socket)];
userNames.splice(userSockets.indexOf(socket), 1);
userSockets.splice(userSockets.indexOf(socket), 1);
if(state == STATE_LOBBY){
// Send new lobby
userSockets.forEach(function(s){s.emit("LOBBY", userNames);});
}else{
// Send disconnect message
userSockets.forEach(function(s){s.emit("DISCONNECT", name);});
}
}
});
// JOIN
socket.on("JOIN", (username) => {
console.log("JOIN request for "+username);
// Check if can enter in lobby
if(state == STATE_LOBBY){
// Add user to lists
userSockets.push(socket);
userNames.push(username);
console.log(userNames);
// Send lobby data
userSockets.forEach(function(s){s.emit("LOBBY", userNames);});
}else{
// When can't enter
socket.emit("LOBBY_CLOSED");
}
});
// START
socket.on("START", () => {
console.log("START request");
// Send LAODING to all users
userSockets.forEach(function(s){s.emit("LOADING");});
// Set state
state = STATE_GAME;
// Create game
boxes = [];
var usedCodes = [];
for(y=0; y<6; y++){
boxes[y] = [];
for(x=0; x<6; x++){
var code;
do{
code = rand(10, 100);
}while(usedCodes.indexOf(code) != -1);
usedCodes.push(code);
boxes[y][x] = {type:BOX_TYPE_TIP, code:code, tip:""};
}
}
// Pick random boxes for key
var keyX = rand(0, 6);
var keyY = rand(0, 6);
var keyCode = boxes[keyY][keyX].code;
boxes[keyY][keyX].type = BOX_TYPE_KEY;
boxes[keyY][keyX].tip = "This is the key";
// Pick random boxes for bombs
var nrBombs = 4;
var bombXs = [];
var bombYs = [];
for(i=0; i a) t += "bigger than";
else if(keyCode < a) t += "less than";
else t += "equal to";
t += " "+a;
tips.push(t);
}
// Key code odd or even
tips.push("The key in the box with an "+(keyCode%2 == 0 ? "even" : "odd")+" number");
// Key not in same column as
for(i=0; i<6; i++){
var c;
do{
c = rand(0, 6);
}while(c == keyX);
var r = rand(0, 6);
tips.push("The key is not in the same column as "+boxes[r][c].code);
}
// Key not in same row as
for(i=0; i<6; i++){
var r;
do{
r = rand(0, 6);
}while(r == keyY);
var c = rand(0, 6);
tips.push("The key is not in the same row as "+boxes[r][c].code);
}
// Key not neighbour of
for(i=0; i<6; i++){
var x;
var y;
do{
x = rand(0, 6);
y = rand(0, 6);
}while(Math.abs(keyX - x) <= 1 && Math.abs(keyY - y) <= 1);
tips.push("The box with the key is not next to "+boxes[y][x].code);
}
// Player is not guard
for(i=0; i {
// Set OK for this player
userOK[userSockets.indexOf(socket)] = true;
// Check if everybody OK
var OK = true;
for(i=0; i {
// When player picked box
if(currentUserID != userSockets.indexOf(socket)) return;
// Get box type
var type = null;
var x;
var y;
for(i=0; i<6; i++){
for(j=0; j<6; j++){
if(boxes[i][j].code == code){
type = boxes[i][j].type;
x = j;
y = i;
break;
}
}
if(type != null) break;
}
// Check type
if(type == BOX_TYPE_TIP || guardID == currentUserID){
// Return tip to user
var tip = boxes[y][x].tip;
var data = {myTurn:false, currentUser:userNames[currentUserID], tip:""};
for(i=0; i {
// When player pressed OK after tip
if(currentUserID != userSockets.indexOf(socket)) return;
// Next player
nextPlayer();
});
});
// Start HTTP server
server.listen(port, hostname, () => {
console.log("Server running at http://"+hostname+":"+port);
});
// Game methods
function nextPlayer(){
// Increment currentPlayerID
currentUserID = (currentUserID+1)%userSockets.length;
console.log("Next player = "+currentUserID+" ("+userNames[currentUserID]+")");
// Show board to every player and listen for one to pick a box
var board = [];
for(y=0; y<6; y++){
board[y] = [];
for(x=0; x<6; x++){
board[y][x] = {type:boxes[y][x].type, code:boxes[y][x].code};
}
}
var userData = {myTurn:false, board:board, currentUser:userNames[currentUserID]};
// Send userData
for(i=0; i