📜 ⬆️ ⬇️

Writing a bot client for schemaverse

image On Habré, there was already a mention of SQL games. But I was all busy and only recently decided to figure out what it is. Quite by chance I chose a schemaverse about which was also already mentioned on the habr.

As I understand it, you get all the fun of the game when you write a bot for it. For this, I chose one of my most favorite languages ​​- javascript. I also decided to visualize the map to see how my ships fly and capture the enemy planets. I will not give a lot of code and SQL queries so as not to inflate an article, you can always see them in the repository .

I chose the bot behavior algorithm to be very simple - build getters, build invaders, and when invaders become enough - fly to capture. Also, along the way, engineers are being built who repair the ships and, if there is enough money, I carry out fleet upgrades.

From the very beginning, I decided to use third-party libraries to a minimum. So, first establish a connection with the database.
')
var config = require('./config.js'); // Postgres connection var pg = require('pg'), conn = "pg://"+config.username+":"+config.password+"@db.schemaverse.com:5432/schemaverse"; var UserModel = require('./models/user'); var CommandProcessor = require('./command_processor'); pg.connect(conn, function(err, client) { if (!err){ var userModel = new UserModel.constructor(client); CommandProcessor(userModel); } else { console.log(err); } }); 

After the connection is established, the user is initialized and so that you can view some statistics in the console and launch the visualizer, I added a command handler.
When a user initializes, information about his planets is collected. Building the miners / invaders / engineers produces each planet for itself. And refueling / upgrade for all ships.
This is a step-by-step strategy, and I could not follow the dependence of the course duration. Therefore, I check if the turn is completed, depending on the duration of the previous move. At the beginning of the new turn, the status of the ships is checked and the handlers are called to subscribe to the "tic" event. Information about the capture of the new planet is obtained from the list of events. In order to capture the planet rather successfully extract fuel from it. This is the only resource of the game. Also, each course recovers course and speed of all flying ships.
When capturing a new planet, it is added to the list of planets and subscribes to the "tic" event.

 var tick = function(){ repair_damaged(); create_miners(); create_attackers(); go_to_conqueror(); } //constructor user.on(tick); 

It’s not very interesting to follow all of this on console output. I added the CommandProcessor module with which you can check the status of the game at any time. At any time, you can expand the list of supported commands. But in more detail I want to tell about the visualizer and the problems that I had to face.

After entering the “map” command, the web and websocket servers are first created.

 var app = require('http').createServer(handler), io = require('socket.io').listen(app, { log: false }); 

The visualizer also subscribes to the “tic” event and sends a message to customers that it is possible to update the map.
In fact, a web server is needed only for the transfer of statics, that is, the websocket of the client.
Existing visualizers only display a general map. My goal was to also display the fleet.

It looks like this:
image
I did when the circles of the planets approached more, because they were closed by ships.

On a larger scale, the map is updated for a very long time. If you move or increase it, you also have to wait a long time. I do not update the map with every sneeze, but wait until the user enters the new desired coordinates. The card responds to the mouse wheel and shuffle. The client transmits the magnification, offset and size of the desired pattern. The server, based on this data, requests objects from the base, draws them to the canvas and sends them back to the client.

 get_map_base64( data.x, data.y, data.w, data.h, data.zoom, data.render_planets, data.render_ships, function(img){ socket.emit('draw', img); } ); 

In theory, the server can draw only ships or only planets, but I do not use it yet.

It was possible to optimize the update rate of the map if: storing the list of planets locally and changing individual planets according to the conquer event, and if not taking all the maps from the base, but split them into squares and taking one per square.
But there are a lot of them to store locally, I decided to save memory, and if you take one by one from the square, then with a large scale you can not see your initial planet. Therefore, I decided not to optimize the process. In addition, with a high magnification, everything is updated fairly quickly.

Link to the repository of the project - https://github.com/peinguin/schemaverse_bot

Source: https://habr.com/ru/post/195322/


All Articles