-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathmain.js
153 lines (127 loc) · 4.69 KB
/
main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
var io = require('socket.io-client');
var socket = io('http://botws.generals.io');
socket.on('disconnect', function() {
console.error('Disconnected from server.');
process.exit(1);
});
socket.on('connect', function() {
console.log('Connected to server.');
/* Don't lose this user_id or let other people see it!
* Anyone with your user_id can play on your bot's account and pretend to be your bot.
* If you plan on open sourcing your bot's code (which we strongly support), we recommend
* replacing this line with something that instead supplies the user_id via an environment variable, e.g.
* var user_id = process.env.BOT_USER_ID;
*/
var user_id = 'my_example_bot_id';
var username = 'Example Bot';
// Set the username for the bot.
// This should only ever be done once. See the API reference for more details.
socket.emit('set_username', user_id, username);
// Join a custom game and force start immediately.
// Custom games are a great way to test your bot while you develop it because you can play against your bot!
var custom_game_id = 'my_private_game';
socket.emit('join_private', custom_game_id, user_id);
socket.emit('set_force_start', custom_game_id, true);
console.log('Joined custom game at http://bot.generals.io/games/' + encodeURIComponent(custom_game_id));
// When you're ready, you can have your bot join other game modes.
// Here are some examples of how you'd do that:
// Join the 1v1 queue.
// socket.emit('join_1v1', user_id);
// Join the FFA queue.
// socket.emit('play', user_id);
// Join a 2v2 team.
// socket.emit('join_team', 'team_name', user_id);
});
// Terrain Constants.
// Any tile with a nonnegative value is owned by the player corresponding to its value.
// For example, a tile with value 1 is owned by the player with playerIndex = 1.
var TILE_EMPTY = -1;
var TILE_MOUNTAIN = -2;
var TILE_FOG = -3;
var TILE_FOG_OBSTACLE = -4; // Cities and Mountains show up as Obstacles in the fog of war.
// Game data.
var playerIndex;
var generals; // The indicies of generals we have vision of.
var cities = []; // The indicies of cities we have vision of.
var map = [];
/* Returns a new array created by patching the diff into the old array.
* The diff formatted with alternating matching and mismatching segments:
* <Number of matching elements>
* <Number of mismatching elements>
* <The mismatching elements>
* ... repeated until the end of diff.
* Example 1: patching a diff of [1, 1, 3] onto [0, 0] yields [0, 3].
* Example 2: patching a diff of [0, 1, 2, 1] onto [0, 0] yields [2, 0].
*/
function patch(old, diff) {
var out = [];
var i = 0;
while (i < diff.length) {
if (diff[i]) { // matching
Array.prototype.push.apply(out, old.slice(out.length, out.length + diff[i]));
}
i++;
if (i < diff.length && diff[i]) { // mismatching
Array.prototype.push.apply(out, diff.slice(i + 1, i + 1 + diff[i]));
i += diff[i];
}
i++;
}
return out;
}
socket.on('game_start', function(data) {
// Get ready to start playing the game.
playerIndex = data.playerIndex;
var replay_url = 'http://bot.generals.io/replays/' + encodeURIComponent(data.replay_id);
console.log('Game starting! The replay will be available after the game at ' + replay_url);
});
socket.on('game_update', function(data) {
// Patch the city and map diffs into our local variables.
cities = patch(cities, data.cities_diff);
map = patch(map, data.map_diff);
generals = data.generals;
// The first two terms in |map| are the dimensions.
var width = map[0];
var height = map[1];
var size = width * height;
// The next |size| terms are army values.
// armies[0] is the top-left corner of the map.
var armies = map.slice(2, size + 2);
// The last |size| terms are terrain values.
// terrain[0] is the top-left corner of the map.
var terrain = map.slice(size + 2, size + 2 + size);
// Make a random move.
while (true) {
// Pick a random tile.
var index = Math.floor(Math.random() * size);
// If we own this tile, make a random move starting from it.
if (terrain[index] === playerIndex) {
var row = Math.floor(index / width);
var col = index % width;
var endIndex = index;
var rand = Math.random();
if (rand < 0.25 && col > 0) { // left
endIndex--;
} else if (rand < 0.5 && col < width - 1) { // right
endIndex++;
} else if (rand < 0.75 && row < height - 1) { // down
endIndex += width;
} else if (row > 0) { //up
endIndex -= width;
} else {
continue;
}
// Would we be attacking a city? Don't attack cities.
if (cities.indexOf(endIndex) >= 0) {
continue;
}
socket.emit('attack', index, endIndex);
break;
}
}
});
function leaveGame() {
socket.emit('leave_game');
}
socket.on('game_lost', leaveGame);
socket.on('game_won', leaveGame);