From a093060b0e8a787e51212b5f2879dc839605da65 Mon Sep 17 00:00:00 2001 From: Matt Strapp Date: Mon, 26 Apr 2021 17:12:01 -0500 Subject: Revert "Refactor jsut about everything" This reverts commit e58a60ed18bde5db28ba96910df518a61b3999b2. --- python/dotsandboxes/static/dotsandboxes.css | 10 + python/dotsandboxes/static/dotsandboxes.html | 50 +++ python/dotsandboxes/static/dotsandboxes.js | 454 +++++++++++++++++++++++++++ 3 files changed, 514 insertions(+) create mode 100644 python/dotsandboxes/static/dotsandboxes.css create mode 100644 python/dotsandboxes/static/dotsandboxes.html create mode 100644 python/dotsandboxes/static/dotsandboxes.js (limited to 'python/dotsandboxes/static') diff --git a/python/dotsandboxes/static/dotsandboxes.css b/python/dotsandboxes/static/dotsandboxes.css new file mode 100644 index 0000000..71b1d3b --- /dev/null +++ b/python/dotsandboxes/static/dotsandboxes.css @@ -0,0 +1,10 @@ + +.footer { + color: #B3B3B3; + margin-bottom: 1ex; +} + +.footer a { + color: #87A0B3; +} + diff --git a/python/dotsandboxes/static/dotsandboxes.html b/python/dotsandboxes/static/dotsandboxes.html new file mode 100644 index 0000000..4e97508 --- /dev/null +++ b/python/dotsandboxes/static/dotsandboxes.html @@ -0,0 +1,50 @@ + + + + + +Dots and Boxes + + + + +
+

Dots and Boxes

+
+
+
+
+
+
+

Size of game:

+
+
+ Rows and Columns +
+ + +
+
+
+

Players:

+
+
Agent 1
+ +
+
+
Agent 2
+ +
+

Fill in the address where an agent can be reached using WebSockets (e.g. ws://127.0.0.1:8089). + If a field is empty a human player is assumed. +

+ +
+
+
+
+ + + + + diff --git a/python/dotsandboxes/static/dotsandboxes.js b/python/dotsandboxes/static/dotsandboxes.js new file mode 100644 index 0000000..11e9447 --- /dev/null +++ b/python/dotsandboxes/static/dotsandboxes.js @@ -0,0 +1,454 @@ +/** + * dotsandboxes.js + * + * Template for the Machine Learning Project course at KU Leuven (2017-2018) + * of Hendrik Blockeel and Wannes Meert. + * + * Copyright (c) 2018 KU Leuven. All rights reserved. + **/ + +function generateGuid() { + var result, i, j; + result = ''; + for(j=0; j<32; j++) { + if( j == 8 || j == 12|| j == 16|| j == 20) + result = result + '-'; + i = Math.floor(Math.random()*16).toString(16).toUpperCase(); + result = result + i; + } + return result; +} + +// GAME LOGIC + +var cur_game = generateGuid(); +var cur_player = 1; +var cur_ended = false; +var points = [0, 0, 0]; +var timelimit = 0.5; +var nb_cols = 6; +var nb_rows = 6; +var data = new Array(0); + +function restart_game() { + //console.log("Restarting game"); + cur_game = generateGuid(); + nb_cols = parseInt(document.getElementById('nb-cols').value); + if (nb_cols == "" || isNaN(nb_cols)) { + nb_cols = 6; + } + nb_rows = parseInt(document.getElementById('nb-rows').value); + if (nb_rows == "" || isNaN(nb_rows)) { + nb_rows = 6; + } + cur_ended = false; + console.log("Starting game", cur_game); + points = [0, 0, 0]; + cur_player = 1; + var old_length = 0; + for (var ri=0; ri= data.length) { + data.push(new Array(0)); + } + var row = data[ri]; + for (var ci=0; ci= row.length) { + row.push({l:0, t:0, p:0, r:0, c:0}); + } + var l = 0; + var t = 0; + var p = 0; + if (ri == nb_rows) { + l = undefined; + p = undefined; + } + if (ci == nb_cols) { + t = undefined; + p = undefined + } + var cell = row[ci]; + cell.l = l; + cell.t = t; + cell.p = p; + cell.r = ri; + cell.c = ci; + } + old_length = row.length; + for (var ci=nb_cols + 1; ci 0) { + if (data[r - 1][c].l != 0 + && data[r - 1][c + 1].l != 0 + && data[r - 1][c].t != 0 + && data[r][c].t != 0) { + won_cell = true; + points[cur_player] += 1; + data[r - 1][c].p = cur_player; + } + } + // Below + if (r < nb_rows) { + if (data[r][c].l != 0 + && data[r][c + 1].l != 0 + && data[r][c].t != 0 + && data[r + 1][c].t != 0) { + won_cell = true; + points[cur_player] += 1; + data[r][c].p = cur_player; + } + } + } + + if (o == "v") { + if (cell.l != 0) { + return; + } + cell.l = cur_player; + // Left + if (c > 0) { + if (data[r][c - 1].l != 0 + && data[r][c].l != 0 + && data[r][c - 1].t != 0 + && data[r + 1][c - 1].t != 0) { + won_cell = true; + points[cur_player] += 1; + data[r][c - 1].p = cur_player; + } + } + // Right + if (c < nb_cols) { + if (data[r][c].l != 0 + && data[r][c + 1].l != 0 + && data[r][c].t != 0 + && data[r + 1][c].t != 0) { + won_cell = true; + points[cur_player] += 1; + data[r][c].p = cur_player; + } + } + } + + msg["score"] = [points[1], points[2]]; + + if (!won_cell) { + cur_player = 3 - cur_player; + msg.nextplayer = cur_player; + } + update_board(); + if (points[1] + points[2] == nb_cols * nb_rows) { + // Game over + var winner = 1 + if (points[2] == points[1]) { + winner = 0; + } + if (points[2] > points[1]) { + winner = 2; + } + cur_ended = true; + msg.type = "end"; + msg.nextplayer = 0; + msg.winner = winner; + } + send_to_agents(msg); +} + +var field_margin = 10; +var cell_width = 40; +var cell_margin = 4; +var player_height = 40; +var width = 400; +var height = 600; +var line_width = 5; + +var player_color = [ + "#E6E6E6", + "#FC6666", + "#0F80FF" +]; + +var svg = d3.select("#playing-area").append("svg") + .attr("width", width) + .attr("height", height) + .append("g") + .attr("transform", "translate("+field_margin+","+field_margin+")"); + +var player = svg.append("g") + .attr("class", "player") + .attr("transform", "translate(0,10)"); + +var field = svg.append("g") + .attr("class", "field") + .attr("transform", "translate(0,"+player_height+")"); + + +function update_board() { + // PLAYERS - enter & update + var player_text = player.selectAll("text") + .data([cur_player, cur_player]); + + player_text = player_text.enter().append("text") + .attr("x", function(c, i) { return i * 100;}) + .merge(player_text) + .text(function(c, i) {return "Player " + (i + 1) + ": "+points[i + 1];}) + .attr("fill", function(c, i) { + if (c == i + 1) { + return player_color[c]; + } else { + return player_color[0]; + } + }); + + // ROWS - enter & update + var rows = field.selectAll(".row") + .data(data) + .attr("fill", function() {return null;}); + + rows.exit().remove(); + + rows = rows.enter().append("g") + .attr("class", "row") + .attr("transform", function(row, i) {return "translate(0," + cell_width * i + ")";}) + .merge(rows); + + // COLS - enter & update + var cols = rows.selectAll(".col") + .data(function(col) {return col;}); + + cols.exit().remove(); + + var cols_enter = cols.enter().append("g") + .attr("class", "col") + .attr("transform", function(col, ri) {return "translate("+cell_width * ri+",0)";}); + + // CELL - enter + cols_enter.append("rect") + .attr("class", "cell") + .attr("rx", cell_margin) + .attr("ry", cell_margin) + .attr("opacity", 0.25) + .attr("x", cell_margin) + .attr("y", cell_margin) + .attr("width", cell_width - 2*cell_margin) + .attr("height", cell_width - 2*cell_margin); + + // HLINE - enter + cols_enter.append("line") + .attr("class", "hline") + .attr("x1", function(cell, ci) {return cell_margin;}) + .attr("x2", function(cell, ci) {return cell_width - cell_margin;}) + .attr("y1", 0) + .attr("y2", 0) + .attr("stroke-linecap", "round") + .attr("stroke", function(cell) {return player_color[cell.t];}); + + cols_enter.append("path") + .attr("d", "M"+cell_margin+",0"+ + "L"+(cell_width/2)+",-"+(cell_width/3)+ + "L"+(cell_width-cell_margin)+",0"+ + "L"+(cell_width/2)+","+(cell_width/3)+"Z") + .attr("stroke", "black") + .attr("stroke-width", 2) + .attr("opacity", "0") + .on("click", function(cell) { + if (agents[cur_player].active == true) { + console.log("Ignoring click, automated agent") + } else { + user_click(cell, "h"); + } + }); + + // VLINE - enter + cols_enter.append("line") + .attr("class", "vline") + .attr("y1", function(cell, ci) {return cell_margin;}) + .attr("y2", function(cell, ci) {return cell_width - cell_margin;}) + .attr("x1", 0) + .attr("x2", 0) + .attr("stroke-linecap", "round") + .attr("stroke", function(cell) {return player_color[cell.l];}); + + cols_enter.append("path") + .attr("d", "M0,"+cell_margin+ + "L-"+(cell_width/3)+","+(cell_width/2)+ + "L0,"+(cell_width-cell_margin)+ + "L"+(cell_width/3)+","+(cell_width/2)+"Z") + .attr("stroke", "black") + .attr("stroke-width", 2) + .attr("opacity", "0") + .on("click", function(cell) { + if (agents[cur_player].active == true) { + console.log("Ignoring click, automated agent"); + } else { + user_click(cell, "v"); + } + }); + + cols = cols_enter + .merge(cols); + + // HLINE - update + cols.selectAll(".hline") + .attr("stroke-width", function(cell) { + if (typeof(cell.t) == "undefined") { + return 0; + } + return line_width; + }) + .attr("stroke", function(cell) {return player_color[cell.t];}); + + // VLINE - update + cols.selectAll(".vline") + .attr("stroke-width", function(cell, ci) { + if (typeof(cell.l) == "undefined") { + return 0; + } + return line_width; + }) + .attr("stroke", function(cell) {return player_color[cell.l];}); + + // CELL - update + cols.selectAll(".cell") + .attr("fill", function(cell) { + if (cell.p == undefined) { + return "white"; + } + return player_color[cell.p]; + }); +} + + +// AGENT CONNECTIONS + +var agents = [ + {}, + {address: undefined, active: false, socket: undefined}, + {address: undefined, active: false, socket: undefined} +]; + +var msg_queue = []; + + +function start_connections() { + for (var i=1; i<3; i++) { + agents[i] = {address:undefined, active: false, socket: undefined}; + var address = document.getElementById('agent'+i).value; + if (address != "") { + //console.log("Starting websocket for agent "+i+" on address "+address); + var agent = agents[i]; + agent.address = address; + agent.socket = new WebSocket(address); + agent.socket.onopen = (function (ii, iagent) { return function(event) { + console.log("Agent "+ii+" connected") + iagent.active = true; + iagent.socket.onmessage = function(event) { + var msg = JSON.parse(event.data); + //console.log("Get msg from agent "+ii, msg); + if (msg.type == "action") { + if (cur_player == ii) { + console.log("Received action from ACTIVE player "+ii, msg); + user_click(data[msg.location[0]][msg.location[1]], msg.orientation); + } else { + console.log("Received action from NON-ACTIVE player "+ii, msg); + } + } + return false; + }; + iagent.socket.onclose = function(event) { + console.log("Closing connection to agent "+ii); + }; + iagent.socket.onerror = function(event) { + console.log("Error on connection to agent "+ii, event); + }; + msg = { + "type": "start", + "player": ii, + "timelimit": timelimit, + "game": cur_game, + "grid": [nb_rows, nb_cols] + }; + iagent.socket.send(JSON.stringify(msg)); + };}(i, agent)); + } + } +} + + +function send_to_agents(msg) { + msg_queue.push(JSON.stringify(msg)); + try_sending_to_agents(); +} + + +function try_sending_to_agents() { + var all_connected = true; + for (var i=1; i<3; i++) { + if (agents[i].address !== undefined && agents[i].active == false) { + all_connected = false; + break; + } + } + if (!all_connected) { + // Wait until all are connected + setTimeout(try_sending_to_agents, 100); + } else { + if (msg_queue.length == 0 ) { + return; + } + var msg = msg_queue.shift(); + console.log("Send msg to agents", msg); + for (var i=1; i<3; i++) { + if (agents[i].active == true) { + agents[i].socket.send(msg); + } + } + } +} + + +// STARTUP + +function restart() { + restart_game(); + update_board(); + start_connections(); +} + +var restartbtn = document.getElementById("restart-btn"); +restartbtn.onclick = function() { + console.log("Restart game"); + restart(); +}; + +restart(); -- cgit v1.2.3