Compare commits

...

1 Commits

Author SHA1 Message Date
dabbott 15b6f2d2a5 WhiteLabel
7 months ago

@ -1,13 +1,4 @@
config = {
secret: "Keenly-Resident-Circular4",
mongoUrl: "mongodb://10.0.0.2:27017",
express: {
port: 8888
},
boundry: {
top: 100,
right: 100
},
creature:{
physical: {
maxEnergy: 20,
@ -31,23 +22,11 @@ config = {
tileDefaultFood: 100,
tileFoodGrowChance: 0.1
},
defaultOwner: "Nobody",
genesisCreaturesPerUser: 20,
maxPop: 10000,
timers: {
preGame: 6000,
gameStep: 3000
preGame: 5000,
gameStep: 100
},
powers:{
transferEnergyBuyCost: 100,
saveCreatureBuyCost: 100000,
spawnCreatureBuyCost: 500000,
mutateCreatureBuyCost: 10000,
feedCreatureBuyCost: 1000,
growFoodBuyCost: 10000,
deleteFoodBuyCost: 50000,
bombBuyCost: 10000,
}
}
module.exports = config

@ -5,42 +5,22 @@ const { v4: uuidv4 } = require('uuid')
worldObj = require("../storageObjects/worldObj")
creatureArr = require("../storageObjects/creatureArr")
userObj = require("../storageObjects/userObj")
function percentify(lower,upper,input){
upper -= lower
input -= lower
return input*100/upper
}
function chooseOwner(){
let playingUsers = []
Object.keys(userObj).forEach(user => {
if (userObj[user]["readyState"]){
playingUsers.push(user)
}
})
let owner = playingUsers[(creatureArr.length % playingUsers.length)]
userObj[owner].addCreature()
return owner
}
class Creature {
constructor(parentName,surName,location, energy, maxEnergy, speed, brain, brainSize, brainComplexity, owner, activationValue, oscillatorFrequency,maxAge,generation,eatFoodLevel, colour) {
this._id = uuidv4()
this.owner = owner || chooseOwner()
this.name = fName.choose()
this.parentName = parentName || this.name
this.surName = surName || lName.choose()
this.fullName = this.name+"."+this.parentName+"."+this.surName
this.maxEnergy = maxEnergy || config.creature.physical.maxEnergy
this.energy = energy || this.maxEnergy
this.facingDirection = Math.ceil(Math.random()*4)
this.location = location || this.placeSelf()
this.frontLoc = this.direction(1)
this.rightLoc = this.direction(2)
this.behindLoc = this.direction(3)
this.leftLoc = this.direction(4)
this.speed = speed || config.creature.physical.defaultSpeed
this.brain = brain || []
this.brainSize = brainSize || config.creature.brain.size
@ -69,27 +49,6 @@ class Creature {
}
return x
},
blockedCheck:() => {
if(worldObj.checkBlocked(this.frontLoc)){
return 100
} else {
return 0
}
},
creatureCheck:() => {
if(worldObj.checkCreature(this.frontLoc)){
return 100
} else {
return 0
}
},
foodCheck:() => {
if(worldObj.checkTileFoodLevel(this.frontLoc) > this.eatFoodLevel){
return percentify(0,config.world.tileMaxFood,worldObj.tiles[JSON.stringify(this.frontLoc)].foodLevel)
} else {
return 0
}
},
energyCheck:() => {
return percentify(0,this.maxEnergy,this.energy)
},
@ -118,66 +77,12 @@ class Creature {
},
},
action: {
moveForward:(input) => {
if (input > this.activationValue && this.alive){
if (this.updateLocation(this.frontLoc)){
messageObj.add("MoveLog", this.fullName+" Moved forward from "+ this.location+" to "+ this.frontLoc)
}
this.facingDirection = 1
return 100
}
return 0
},
moveRight:(input) => {
if (input > this.activationValue && this.alive){
if (this.updateLocation(this.rightLoc)){
messageObj.add("MoveLog", this.fullName+" Moved right from "+ this.location+" to "+ this.rightLoc)
}
this.facingDirection = 2
return 100
}
return 0
},
moveBack:(input) => {
if (input > this.activationValue && this.alive){
if (this.updateLocation(this.behindLoc)){
messageObj.add("MoveLog", this.fullName+" Moved backwards from "+ this.location+" to "+ this.behindLoc)
}
this.facingDirection = 3
return 100
}
return 0
},
moveLeft:(input) => {
if (input > this.activationValue && this.alive){
if (this.updateLocation(this.leftLoc)){
messageObj.add("MoveLog", this.fullName+" Moved left from "+ this.location+" to "+ this.leftLoc)
}
this.facingDirection = 4
return 100
}
return 0
},
eat:(input) => {
worldObj.checkBlocked(this.frontLoc)
if (input > this.activationValue && worldObj.tiles[JSON.stringify(this.frontLoc)].foodLevel > 0 && this.alive){
this.energy += config.world.foodReward
if (this.energy > this.maxEnergy){
userObj[this.owner].addEnergy(this.energy-this.maxEnergy)
this.energy = this.maxEnergy
}
worldObj.tiles[JSON.stringify(this.frontLoc)].foodLevel -= 1
return 100
}
return 0
},
mate:(input) => {
if (input > this.activationValue && creatureArr.length < config.maxPop && this.alive && worldObj.checkBlocked(this.location) && this.energy > (config.creature.physical.birthCost +1)){
if (input > this.activationValue && creatureArr.length < config.maxPop && this.alive && this.energy > (config.creature.physical.birthCost +1)){
// TODO: Figure out why colour Arr sometimes becomes a string.
if(typeof this.colour == "string"){
this.die()
this.die( this.colour)
return false
}
try {
@ -195,42 +100,28 @@ class Creature {
colour: this.colour
})))
if (!worldObj.checkBlocked(this.behindLoc)){
if (true){
this.energy -= config.creature.physical.birthCost
this.births += 1
userObj[this.owner].addCreature()
let baby = new Creature(this.name,obj.surName,this.behindLoc,config.creature.physical.birthEnergy,obj.maxEnergy,obj.speed,obj.brain,obj.brainSize,obj.brainComplexity,this.owner,obj.activationValue,obj.oscillatorFrequency,obj.maxAge, this.generation+1,obj.eatFoodLevel, obj.colour)
messageObj.add("Birth", this.fullName+" gave birth to "+baby.fullName)
creatureArr.push(baby)
messageObj.add("Location", this.fullName+" gave birth to "+ baby.fullName+" at "+this.location+", the child is at "+baby.location)
return 100
}
return 0
}
catch (e){
this.die()
this.die(e)
}
}
return 0
},
fight:(input) => {
if (input > this.activationValue && worldObj.checkCreature(this.frontLoc)&& this.alive){
this.kills += 1
userObj[this.owner].addKill()
messageObj.add("Fight",(this.fullName+" Killed "+worldObj.tiles[JSON.stringify(this.frontLoc)].creature.fullName)+" they have killed "+this.kills+" creatures")
worldObj.tiles[JSON.stringify(this.frontLoc)].creature.die("they were killed by "+this.fullName)
return 100
}
return 0
}
}
}
mutate(obj){
let mod = 0
if (Math.random() < config.creature.physical.mutateFraction){
userObj[this.owner].addMutant()
obj.surName = (this.name+"_"+this.surName)
if(Math.random() > 0.5){
mod = 1
@ -265,96 +156,8 @@ class Creature {
}
return obj
}
updateLocation(arr){
if(arr[0] < 0 ||arr[1] < 0){
this.die()
return this.location
} else if (arr[1] > config.boundry.right || arr[0] > config.boundry.top) {
this.die()
return this.location
} else {
worldObj.checkBlocked(arr)
if (this.location !== undefined){
worldObj.checkBlocked(this.location)
worldObj.tiles[JSON.stringify(this.location)].creature = {}
worldObj.tiles[JSON.stringify(arr)].creature = this
}
this.location = arr
this.frontLoc = this.direction(1)
this.rightLoc = this.direction(2)
this.behindLoc = this.direction(3)
this.leftLoc = this.direction(4)
return true
}
}
direction(desiredLocation){
if(desiredLocation[0] < 0 || desiredLocation[1] < 0 || desiredLocation[0] > config.boundry.top || desiredLocation[1] > config.boundry.right){
this.die()
return this.location
}
worldObj.checkBlocked([this.location[0]+1, this.location[1]])
worldObj.checkBlocked([this.location[0]-1, this.location[1]])
worldObj.checkBlocked([this.location[0],this.location[1]+1])
worldObj.checkBlocked([this.location[0],this.location[1]-1])
switch (desiredLocation) {
case 1:
switch (this.facingDirection) {
case 1:
return [this.location[0]+1,this.location[1]]
case 2:
return [this.location[0],this.location[1]+1]
case 3:
return [this.location[0]-1,this.location[1]]
case 4:
return [this.location[0],this.location[1]-1]
}
case 2:
switch (this.facingDirection) {
case 1:
return [this.location[0],this.location[1]+1]
case 2:
return [this.location[0]-1,this.location[1]]
case 3:
return [this.location[0],this.location[1]-1]
case 4:
return [this.location[0]+1,this.location[1]]
}
case 3:
switch (this.facingDirection) {
case 1:
return [this.location[0]-1,this.location[1]]
case 2:
return [this.location[0],this.location[1]-1]
case 3:
return [this.location[0]+1,this.location[1]]
case 4:
return [this.location[0],this.location[1]+1]
}
case 4:
switch (this.facingDirection) {
case 1:
return [this.location[0],this.location[1]-1]
case 2:
return [this.location[0]+1,this.location[1]]
case 3:
return [this.location[0],this.location[1]+1]
case 4:
return [this.location[0]-1,this.location[1]]
}
}
}
placeSelf(){
let arr = [Math.floor(Math.random()*config.boundry.top),Math.floor(Math.random()*config.boundry.right)]
worldObj.checkBlocked(arr)
if(!worldObj.checkBlocked(arr) || worldObj.tiles[JSON.stringify(arr)].creature.fullName == this.fullName){
this.updateLocation(arr)
worldObj.tiles[JSON.stringify(arr)].creature = this
messageObj.add("Location", this.fullName+" Initially placed at "+this.location)
} else {
this.die("they were placed in tile "+ arr +" which is occupied by "+ worldObj.tiles[JSON.stringify(arr)].creature.fullName)
}
return arr
}
randomBrain() {
for (let braindex = 0; braindex < this.brainSize; braindex++) {
let brainPath = []
@ -403,17 +206,9 @@ class Creature {
}
die(deathReason){
if (this.alive){
userObj[this.owner].takeCreature()
this.alive = false
// worldObj.checkBlocked(this.location)
if (worldObj.checkCreature(this.location)){
worldObj.tiles[JSON.stringify(this.location)].creature = {}
} else {
console.log(this.fullName+" does not have a tile!")
}
console.log(this.fullName+" died: " + deathReason)
}
this.location = [null, null]
messageObj.add("Death",(this.fullName+" died because "+deathReason))
return 0
}
}

@ -1,14 +1,7 @@
const User = require("./classes/userClass")
config = require("../config")
worldObj = require("./storageObjects/worldObj")
userObj = require("./storageObjects/userObj")
messageObj = require("./storageObjects/messagesObj")
creaturesObj = require("./storageObjects/creatureObj")
creatureArr = require("./storageObjects/creatureArr")
svg = require("../webServer/gameSVG")
mongo = require("./mongoHelp")
Creature = require("./classes/creatureClass")
@ -17,28 +10,22 @@ Creature = require("./classes/creatureClass")
function setupGame(){
return new Promise((resolve,reject) => {
messageObj.wipe()
creaturesObj = {}
creatureArr = []
worldObj.clean()
// TODO: Figure out why this is in set timeout
setTimeout(() => {
numCreatures = 0
Object.keys(userObj).forEach((user) => {
if(userObj[user]["readyState"] == true){
numCreatures += config.genesisCreaturesPerUser
}
})
numCreatures = 10000
console.log("Spawning "+numCreatures+" creatures")
for (let index = 0; index < numCreatures; index++) {
creatureArr.push(new Creature())
}
}, config.timers.preGame*0.75)
}, 1000)
setTimeout(() => {
if (creatureArr.length == 0){
return reject(false)
} else {
svg.setup()
return resolve(true)
}
}, config.timers.preGame);
@ -58,36 +45,22 @@ function gameLoop(){
creatureArr.splice(index,1)
}
})
// messageObj.print("Death")
// messageObj.print("Birth")
// messageObj.print("Location")
console.log("Dead: "+deadCreatureCount)
console.log("World: "+worldObj.id+" "+worldObj.universe+" "+worldObj.step)
console.log("Creatures: "+creatureArr.length)
console.log(new Date)
messageObj.wipe()
if (creatureArr.length == 0){
console.log("All Dead")
Object.keys(userObj).forEach(user => {
userObj[user].clean()
})
clearInterval(loop)
return resolve(true)
} else {
console.log(creatureArr[0].fullName, creatureArr[0].location,creatureArr[0].energy+"/"+creatureArr[0].maxEnergy, creatureArr[0].age+"/"+creatureArr[0].maxAge, creatureArr[0].generation,creatureArr[0].births,creatureArr[0].kills)
console.log(creatureArr[0].fullName,creatureArr[0].energy+"/"+creatureArr[0].maxEnergy, creatureArr[0].age+"/"+creatureArr[0].maxAge, creatureArr[0].generation)
}
worldObj.step += 1
svg.make()
}, config.timers.gameStep)
})
}
function gifGen(){
return new Promise((resolve,reject) => {
})
}
function recurse(){
setupGame().then(() => {
gameLoop().then(()=> {
@ -104,9 +77,6 @@ function recurse(){
})
}
mongo.get("algoZoo", "users", {readyState: true}).then(userArr => {
userArr.forEach(user => {
new User(user.name, user.pass,user._id, user.energy, user.powers)
})
recurse()
})
recurse()

@ -1,16 +0,0 @@
userObj = require("./storageObjects/userObj.js")
function handleAction(actionObj, user){
switch (actionObj.action) {
case "buy":
userObj[user.data.name].purchasePower(actionObj.power)
return {status: "Done!"}
case "bomb":
userObj[user.data.name].bomb(actionObj.location, actionObj.radius)
return {status: "Done!"}
default:
break;
}
}
module.exports = handleAction

@ -1,57 +0,0 @@
var MongoClient = require('mongodb').MongoClient
config = require("../config")
var url = config.mongoUrl
var options= {
useNewUrlParser: true,
useUnifiedTopology: true}
function put(db,collection, object){
const client = new MongoClient(url, options)
client.connect()
client.db(db).collection(collection).insertOne(object).then((value) =>{client.close();return value})
}
exports.put = put
function get(db, collection, object){
const client = new MongoClient(url, options)
client.connect()
return client.db(db).collection(collection).find(object).toArray().then((value) =>{client.close();return value})
}
exports.get = get
function getUnique(db, collection, field,object){
const client = new MongoClient(url, options)
client.connect()
return client.db(db).collection(collection).distinct(field,object).then((value) =>{client.close();return value})
}
exports.getUnique = getUnique
function aggregate(db,collection,agg){
const client = new MongoClient(url, options)
client.connect()
return client.db(db).collection(collection).aggregate(agg).toArray().then((value) =>{client.close();return value})
}
exports.aggregate = aggregate
function deleteOne(db, collection, object) {
const client = new MongoClient(url, options)
client.connect()
client.db(db).collection(collection).deleteOne(object).then((value) =>{client.close();return value})
}
exports.deleteOne = deleteOne
function update(db, collection, search,update) {
const client = new MongoClient(url, options)
client.connect()
client.db(db).collection(collection).updateOne(search,{$set:update}).then((value) =>{client.close();return value})
}
exports.update = update

@ -1,2 +0,0 @@
// creaturesObj = {}
// module.exports = creaturesObj

@ -1,29 +0,0 @@
worldObj = require("../storageObjects/worldObj")
messageObj = {
messages: [],
add:(level, message) => {
messageObj.messages.push([level,message, worldObj.step])
},
print:(level)=> {
messageObj.messages.forEach((element,index) => {
if (element[0] == level){
console.log("Message: "+element[0]+": "+element[1])
messageObj.messages.splice(index,1)
}
})
},
wipe:(length = 0)=> {
if (length == 0){
messageObj.messages = []
} else {
messageObj.messages.forEach((message,index) => {
if (message[2] < (worldObj.step-length)){
messageObj.messages.splice(index,1)
}
})
}
}
}
module.exports = messageObj

@ -1,2 +0,0 @@
userObj = {}
module.exports = userObj

@ -1,62 +1,21 @@
config = require("../../config")
const { v4: uuidv4 } = require('uuid')
svg = require("../../webServer/gameSVG")
userObj = require("../storageObjects/userObj")
worldObj = {
tiles: {},
id: uuidv4(),
step: 0,
universe: 0,
// stop stringifying outside, do it in you bad one
makeTile:(stringifiedArr) => {
if (stringifiedArr === undefined){
return 0
}
if (typeof worldObj.tiles[JSON.stringify(stringifiedArr)] == "undefined" || Object.keys(worldObj.tiles[JSON.stringify(stringifiedArr)]).length == 0){
worldObj.tiles[stringifiedArr] = {
creature: {},
foodLevel: config.world.tileDefaultFood,
}
}
return 100
},
checkBlocked: (arr) => {
if (arr === undefined){
return true
}
if (worldObj.checkCreature(arr)){
return true
} else {
return false
}
},
checkCreature: (arr) => {
if (!worldObj.tiles[JSON.stringify(arr)]){
worldObj.makeTile(JSON.stringify(arr))
}
if (typeof worldObj.tiles[JSON.stringify(arr)].creature.fullName == "undefined"){
return false
} else {
return worldObj.tiles[JSON.stringify(arr)].creature.fullName
}
//Below here, add world status functions, so when the creature looks for input from outside itself, this is where it will source that from.
custom:{
},
checkTileFoodLevel: (arr)=> {
if (!worldObj.tiles[JSON.stringify(arr)]){
worldObj.makeTile(JSON.stringify(arr))
}
return worldObj.tiles[JSON.stringify(arr)].foodLevel
},
clean: () => {
delete worldObj.tiles
delete worldObj.id
worldObj.custom = {}
worldObj.id = uuidv4()
worldObj.tiles = {}
worldObj.universe += 1
worldObj.step = 0
}

@ -1,2 +1 @@
require("./webServer/express")
require("./game/gameControl.js")

@ -1,154 +0,0 @@
express = require('express')
const jwt = require('jsonwebtoken')
mongo = require("../game/mongoHelp")
config = require("../config")
require("./websocket.js")
creatureArr = require("../game/storageObjects/creatureArr")
worldObj = require("../game/storageObjects/worldObj")
messageObj = require("../game/storageObjects/messagesObj")
userObj = require("../game/storageObjects/userObj")
svg = require("./gameSVG")
userManage = require("../game/userManage/userManage")
handleAction = require('../game/handleAction')
const app = express()
module.exports = app
const authenticateJWT = (req, res, next) => {
const authHeader = req.headers.authorization;
if (authHeader) {
const token = authHeader.split(' ')[1];
jwt.verify(token, config.secret, (err, user) => {
if (err) {
console.log(err)
return res.send({"Error": "Auth Failure"})
}
req.user = user
next();
});
} else {
res.redirect(401, "/");
}
}
app.use(express.json(),function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*')
res.setHeader('Access-Control-Allow-Methods', '*')
res.setHeader('Access-Control-Allow-Headers', '*')
res.setHeader('Content-Type', 'application/json')
res.setHeader('Access-Control-Allow-Credentials', true)
next()
})
app.get('/creatures', function (req, res) {
liteArr = JSON.parse(JSON.stringify(creatureArr))
liteArr.forEach(creature => {
delete creature.synapses
delete creature.name
delete creature.parentName
delete creature.surName
delete creature.brain
delete creature.facingDirection
delete creature.frontLoc
delete creature.rightLoc
delete creature.behindLoc
delete creature.leftLoc
delete creature.speed
delete creature.brainSize
delete creature.brainComplexity
delete creature.activationValue
delete creature.oscillatorFrequency
delete creature.eatFoodLevel
delete creature.alive
})
res.send(JSON.stringify(liteArr))
// res.send(JSON.stringify(creatureArr))
})
app.get('/creature/:creatureID', function (req, res) {
res.send(JSON.stringify(creatureArr.find(creature => creature._id == req.params.creatureID)))
})
app.get('/world', function (req, res) {
res.send(JSON.stringify(worldObj))
})
app.get('/world/:tile1/:tile2', function (req, res) {
let arr = [parseInt(req.params.tile1),parseInt(req.params.tile2)]
if (arr[0] <= config.boundry.top && arr[0] >= 0 && arr[1] <= config.boundry.right && arr[1] >= 0 ) {
worldObj.checkBlocked(arr)
res.send(JSON.stringify(worldObj.tiles[JSON.stringify(arr)]))
} else {
res.send(JSON.stringify("Invalid Tile"))
}
})
app.get('/messages', function (req, res) {
res.send(JSON.stringify(messageObj.messages))
})
app.get('/config', function (req, res) {
res.send(JSON.stringify(config))
})
app.get('/users', function (req, res) {
copy = JSON.parse(JSON.stringify(userObj))
Object.keys(copy).forEach((user) => {
delete copy[user].pass
})
res.send(JSON.stringify(copy))
})
app.get('/users/:userName', function (req, res) {
copy = JSON.parse(JSON.stringify(userObj[req.params.userName]))
delete copy.pass
res.send(JSON.stringify(copy))
})
// app.get('/creature', function (req, res) {
// res.send(JSON.stringify(creatureObj))
// })
app.get('/worldMap', function (req, res) {
res.setHeader('Content-Type', 'image/svg+xml')
res.send(svg.image)
})
app.post('/login', (req, res) => {
userManage.login(req.body.name, req.body.pass).then(jwt => {res.send(JSON.stringify(jwt))}).catch(e => {
res.status(401)
res.send(JSON.stringify(e))
})
})
app.post('/register', (req, res) => {
userManage.register(req.body.name, req.body.pass).then(jwt => {res.send(JSON.stringify(jwt))}).catch(e => {
res.status(401)
res.send(JSON.stringify(e))
})
})
app.post('/action',authenticateJWT,(req, res) => {
res.send(handleAction(req.body,req.user))
// userObj[req.user.data.id].transfer(req.body.tokens,req.body.id).then(tokens => (res.end(tokens))).catch(e => {res.send(JSON.stringify(errorObj)); console.log(e)})
})
app.listen(config.express.port)
// users get excess power from creatures eating,
// between seasons users can vote on changes to the config file
// proportional voting!

@ -1,52 +0,0 @@
config = require("../config")
creatureArr = require("../game/storageObjects/creatureArr")
worldObj = require("../game/storageObjects/worldObj")
var svg = require('svg-builder')
fs = require('fs')
const path = require('path');
svg.width("100%")
svg.height("100%")
svg.viewBox("0 0 "+config.boundry.top+" "+config.boundry.right)
var rgb2hex = require('rgb2hex')
gameImage = {
setup: () =>{
console.log("setup",worldObj.id)
fs.mkdir(path.join(__dirname +"/mapImages/tmp/", worldObj.id), (err) => {
if (err) {
return console.error(err);
}
console.log('Directory created successfully!')
})
},
make:() => {
svg.reset()
creatureArr.forEach((creature,index) => {
if (typeof creature.location != "undefined" && creature.location[0] != null && typeof creature.colour != "string"){
colour = creature.colour
svg.circle({
r: 1,
fill: rgb2hex('rgb('+colour[0]+','+colour[1]+','+colour[2]+')').hex,
stroke: rgb2hex('rgb('+colour[0]+','+colour[1]+','+colour[2]+')').hex,
cx: creature.location[0],
cy: creature.location[1]
}).text({
x: creature.location[0],
y: creature.location[1],
'font-family': 'helvetica',
'font-size': 0.1,
stroke : '#000',
fill: '#fff'
}, creature.owner[0])
}
})
gameImage.image = svg.render()
fs.writeFile(__dirname +"/mapImages/tmp/"+worldObj.id+"/"+worldObj.step+".svg", gameImage.image, function (err) {
if (err) return console.log(err)
})
},
image: ""
}
module.exports = gameImage

@ -1,11 +0,0 @@
const { WebSocketServer } = require('ws');
const wss = new WebSocketServer({ port: 8889 });
wss.on('connection', function connection(ws) {
ws.on('message', function message(data) {
console.log('received: %s', data);
});
ws.send('something');
});
Loading…
Cancel
Save