1 module vindinium.game_objs; 2 3 import stdx.data.json; 4 import std.conv; 5 import std.bitmanip; 6 7 struct Pos { 8 uint x, y; 9 10 void update_from_json(JSONValue json) { 11 auto pos = json.get!(JSONValue[string]); 12 13 this.x = pos["x"].get!double.to!uint; 14 this.y = pos["y"].get!double.to!uint; 15 } 16 } 17 18 struct Hero { 19 int id; 20 string name; 21 string user_id; 22 uint elo; 23 Pos pos; 24 uint life; 25 uint gold; 26 uint mine_count; 27 Pos spawn; 28 bool crashed; 29 30 void update_from_json(JSONValue json) { 31 auto hero = json.get!(JSONValue[string]); 32 33 this.id = hero["id"].get!double.to!int; 34 this.name = hero["name"].get!string; 35 this.pos.update_from_json(hero["pos"]); 36 this.life = hero["life"].get!double.to!uint; 37 this.gold = hero["gold"].get!double.to!uint; 38 this.mine_count = hero["mineCount"].get!double.to!uint; 39 this.spawn.update_from_json(hero["spawnPos"]); 40 this.crashed = hero["crashed"].get!bool; 41 42 // might not be in the JSON response, as they're training dummies 43 if("elo" in hero) this.elo = hero["elo"].get!double.to!uint; 44 if("userId" in hero) this.user_id = hero["userId"].get!string; 45 } 46 } 47 48 struct Board { 49 struct Tile { 50 enum Type : ubyte { 51 Empty, 52 Wood, 53 Hero, 54 Tavern, 55 Mine 56 } 57 58 private: 59 mixin(bitfields!( 60 // type of the item 61 Type, "_type", 3, 62 // is the tavern neutral? 63 bool, "_neutral", 1, 64 // hero ID 65 uint, "_id", 4)); 66 67 public: 68 Type type() { return _type; } 69 bool neutral() { 70 assert(type == Type.Mine); 71 return _neutral; 72 } 73 74 uint id() { 75 assert(type == Type.Hero || type == Type.Mine); 76 return _id; 77 } 78 79 this(Type type, uint id) { 80 assert(type == Type.Hero || type == Type.Mine); 81 this._type = type; 82 this._id = id; 83 this._neutral = false; 84 } 85 86 this(Type type) { 87 this._type = type; 88 this._neutral = true; 89 } 90 } 91 92 // board dimentions 93 uint size; 94 95 // [x][y] 96 Tile[][] tiles; 97 98 void update_from_json(JSONValue json) { 99 auto board = json.get!(JSONValue[string]); 100 101 immutable size = board["size"].get!double.to!uint; 102 auto tiles_str = board["tiles"].get!string; 103 104 assert((size * size) == (tiles_str.length/2), 105 "Size vs actual tile string length mismatch!"); 106 107 if(this.size != size) { 108 // reallocate tiles 109 this.tiles = new Tile[][](size, size); 110 } 111 this.size = size; 112 113 uint idx = 0; 114 foreach(y; 0..size) { 115 foreach(x; 0..size) { 116 Tile t; 117 string tile = tiles_str[idx .. idx + 2]; 118 119 if(tile == " ") { 120 t = Tile(Tile.Type.Empty); 121 } 122 else if(tile == "##") { 123 t = Tile(Tile.Type.Wood); 124 } 125 else if(tile[0] == '@') { 126 t = Tile(Tile.Type.Hero, tile[1 .. 2].to!uint); 127 } 128 else if(tile == "[]") { 129 t = Tile(Tile.Type.Tavern); 130 } 131 else if(tile[0] == '$') { 132 if(tile[1] == '-') { 133 t = Tile(Tile.Type.Mine); 134 } 135 else { 136 t = Tile(Tile.Type.Mine, tile[1 .. 2].to!uint); 137 } 138 } 139 else { 140 assert(false, "Invalid tile on board: `" ~ tile ~ "`"); 141 } 142 143 this.tiles[x][y] = t; 144 idx += 2; 145 } 146 } 147 } 148 } 149 150 struct Game { 151 string id; 152 uint turn; 153 uint max_turns; 154 Hero[] heros; 155 Board board; 156 bool finished; 157 158 void update_from_json(JSONValue json) { 159 auto game = json.get!(JSONValue[string]); 160 161 this.id = game["id"].get!string; 162 this.turn = game["turn"].get!double.to!uint; 163 this.max_turns = game["maxTurns"].get!double.to!uint; 164 165 auto heroes_json = game["heroes"].get!(JSONValue[]); 166 if(!this.heros.length) { 167 this.heros = new Hero[](heroes_json.length); 168 } 169 170 foreach(i, hero_json; heroes_json) { 171 this.heros[i].update_from_json(hero_json); 172 } 173 174 this.board.update_from_json(game["board"]); 175 this.finished = game["finished"].get!bool; 176 } 177 } 178 179 struct GameResponse { 180 Game game; /// initial game state 181 Hero hero; /// the player's hero 182 string token; 183 string view_url; 184 string play_url; 185 186 void update_from_json(JSONValue json) { 187 auto gr = json.get!(JSONValue[string]); 188 189 this.game.update_from_json(gr["game"]); 190 this.hero.update_from_json(gr["hero"]); 191 this.token = gr["token"].get!string; 192 this.view_url = gr["viewUrl"].get!string; 193 this.play_url = gr["playUrl"].get!string; 194 } 195 }