Skip to content

Instantly share code, notes, and snippets.

@xreiju
Created August 5, 2018 04:47
Show Gist options
  • Save xreiju/6b3c19a722c7ad59de050083736f413e to your computer and use it in GitHub Desktop.
Save xreiju/6b3c19a722c7ad59de050083736f413e to your computer and use it in GitHub Desktop.
dependency: vibe-d
import vibe.http.websockets;
import vibe.core.log;
import vibe.core.core;
import vibe.inet.url;
import std.json;
import std.net.curl;
import std.parallelism;
import std.random;
import std.concurrency;
import std.stdio;
import std.algorithm;
import std.conv;
import std.string;
import std.range;
const baseURL = "misskey.xyz";
const apiURL = "https://" ~ baseURL ~ "/api";
const wsURL = "wss://" ~ baseURL;
string userid, i;
string jsonPost(string url, string[string] param) {
HTTP http = HTTP();
http.addRequestHeader("Content-Type", "application/json");
return post(url, JSONValue(param).toString, http).to!string;
}
auto connectReversi() {
logInfo(wsURL ~ "/?i=" ~ i);
auto url = URL(wsURL ~ "/games/reversi?i=" ~ i);
auto ws = connectWebSocket(url);
logInfo("WebSocket connected");
return ws;
}
void main(string[] args) {
if(args.length <= 2) return;
userid = args[1];
i = args[2];
auto ws = connectReversi();
while(ws.waitForData()) {
auto txt = ws.receiveText;
auto json = parseJSON(txt);
auto data = json["body"];
auto type = json["type"].str;
if(type == "invited") {
logInfo("Got invited by %s!", data["parent"]["username"].str);
auto res = jsonPost(apiURL~"/games/reversi/match",
["i": i, "userId": data["parent"]["id"].str]
).parseJSON;
spawn(&startGame, i, res["id"].str); // 各試合用のプロセスをつくる
}
}
logFatal("Connection lost!");
}
void startGame(string i, string id) {
logInfo("received: %s", id);
auto url = URL("%s/games/reversi-game?i=%s&game=%s".format(wsURL, i, id));
auto ws = connectWebSocket(url);
logInfo("Game %s's websocket connected", id);
logInfo(url.to!string);
ws.send(["type": "accept"].JSONValue.toString);
Othello o;
while(ws.waitForData()) {
// なぜかtype: setが一回来たあと多分ここですら実行されなくなってしまう
auto txt = ws.receiveText;
auto json = txt.parseJSON;
auto type = json["type"].str;
auto data = json["body"];
json.writeln;
type.writeln;
switch(type) {
case "started":
data["user1Id"].str.writeln;
data["black"].integer.writeln;
bool tmp = data["user1Id"].str == userid && data["black"].integer == 1 || data["user2Id"].str == userid && data["black"].integer == 2;
o = new Othello(data["settings"]["map"].to!string[].to!(char[][]), tmp);
//if(tmp) ws.send(["type": "set", "pos": o.think().to!string].JSONValue.toString);
break;
case "set":
o.onSet(data);
break;
default:
break;
}
}
// ここにもこない
logFatal("connection lost! %s", id);
}
class Othello {
char[][] board;
const ulong height, width;
bool botColor;
this(char[][] board, bool botColor) {
this.board = board;
this.botColor = botColor;
height = board.length;
width = board[0].length;
foreach(i; 0..height) foreach(j; 0..width) {
if(isPlaceable(i, j)) board[i][j] = 'o';
}
board.each!writeln;
}
auto dh = [1,1,0,-1,-1,-1,0,1];
auto dw = [0,-1,-1,-1,0,1,1,1];
bool isPlaceable(ulong h, ulong w) {
if(h >= height || w >= width)
return false;
if(board[h][w] != '-')
return false;
foreach(i; 8.iota) {
if(isPlaceable(h, w, dh[i], dw[i]))
return true;
}
return false;
}
// TODO: バグだらけ^q^ 適当にネットから拾ってきた
bool isPlaceable(ulong h, ulong w, int dh, int dw) {
char myStone = botColor ? 'b' : 'w';
h += dh, w += dw;
if(h < 0 || h >= height || w < 0 || w >= width)
return false;
if(board[h][w] == myStone) return false;
if(board[h][w] == ' ') return false;
while(h >= 0 && h < height && w >= 0 && w < width) {
if(board[h][w] == ' ')
return false;
if(board[h][w] == myStone)
return true;
h += dh;
w += dw;
}
return false;
}
void onSet(JSONValue data) {
auto pos = data["pos"].integer;
pos.writeln;
board[pos/width][pos%width] = data["color"].str[0];
foreach(i; 0..height) foreach(j; 0..width) {
if(isPlaceable(i, j)) board[i][j] = 'o';
}
board.each!writeln;
}
// TODO
int think() {
return 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment