mirror of https://github.com/dirtbags/tanks.git
Merge branch 'master' of woozle.org:projects/ctf/tanks
This commit is contained in:
commit
f202312979
|
@ -39,7 +39,7 @@ def read_tank(infile):
|
|||
def post_tank(headers, code, url):
|
||||
token = os.environ.get('token')
|
||||
if not token:
|
||||
raise RuntimeError("Must provide token in 'token' environment variable")
|
||||
token = open('token').readline().strip()
|
||||
request = {}
|
||||
request['token'] = token
|
||||
request['name'] = headers.get('Tank-Name', '')
|
||||
|
|
|
@ -37,6 +37,10 @@
|
|||
<script type="application/javascript">
|
||||
window.onload = function() { design(); update(); };
|
||||
function onSubmit() {
|
||||
if ($('[name="name"]').val() === "") {
|
||||
$('#submit-feedback').html("No name?");
|
||||
return;
|
||||
}
|
||||
$('#submit-feedback').html("Submitting...");
|
||||
|
||||
// http://stackoverflow.com/questions/169506/obtain-form-input-fields-using-jquery
|
||||
|
@ -78,19 +82,26 @@
|
|||
$('[name="' + name + '"]').val(val);
|
||||
};
|
||||
|
||||
var finishedreqs = 0;
|
||||
var request = makerequest("name");
|
||||
request.done(function(msg) {
|
||||
$('#submit-feedback').html("");
|
||||
setval("name", msg);
|
||||
|
||||
var gotreq = function() {
|
||||
finishedreqs++;
|
||||
if (finishedreqs == 13) {
|
||||
$('#submit-feedback').html("Retrieved.");
|
||||
}
|
||||
};
|
||||
request = makerequest("author");
|
||||
request.done(function(msg) { setval("author", msg); } );
|
||||
request.done(function(msg) { gotreq(); setval("author", msg); } );
|
||||
request = makerequest("color");
|
||||
request.done(function(msg) { setval("color", msg.replace(/[\r\n]/g, '')); update(); } );
|
||||
request.done(function(msg) { gotreq(); setval("color", msg.replace(/[\r\n]/g, '')); update(); } );
|
||||
request = makerequest("program");
|
||||
request.done(function(msg) { setval("program", msg); } );
|
||||
request.done(function(msg) { gotreq(); setval("program", msg); } );
|
||||
var sensorfunc = function(id) {
|
||||
return function(msg) {
|
||||
gotreq();
|
||||
var vals = msg.replace(/[\r\n]/g, '').split(" ");
|
||||
setval("s"+id+"r", vals[0]);
|
||||
setval("s"+id+"a", vals[1]);
|
||||
|
|
74
jstanks.js
74
jstanks.js
|
@ -73,22 +73,20 @@ var SPACING = 150;
|
|||
var MEMORY_SIZE = 10;
|
||||
|
||||
var Forf = function() {
|
||||
this.datastack = [];
|
||||
this.cmdstack = [];
|
||||
this.mem = new Object();
|
||||
this.builtins = new Object();
|
||||
|
||||
this.builtins["debug!"] = function(myforf) { document.getElementById('debug').innerHTML = myforf.datastack.pop(); };
|
||||
this.builtins["debug!"] = function(myforf) { document.getElementById('debug').innerHTML = myforf.popData(); };
|
||||
var unfunc = function(func) {
|
||||
return function(myforf) {
|
||||
var a = myforf.datastack.pop();
|
||||
var a = myforf.popData();
|
||||
myforf.datastack.push(~~func(a)); // truncate, FIXME
|
||||
};
|
||||
};
|
||||
var binfunc = function(func) {
|
||||
return function(myforf) {
|
||||
var a = myforf.datastack.pop();
|
||||
var b = myforf.datastack.pop();
|
||||
var a = myforf.popData();
|
||||
var b = myforf.popData();
|
||||
myforf.datastack.push(~~func(b,a)); // truncate?, FIXME
|
||||
};
|
||||
};
|
||||
|
@ -119,22 +117,22 @@ var Forf = function() {
|
|||
this.builtins["abs"] = unfunc(function(a) { return Math.abs(a); });
|
||||
// FIXME: the three following functions can only manipulate numbers in cforf
|
||||
this.builtins["dup"] = function(myforf) {
|
||||
var val = myforf.datastack.pop();
|
||||
var val = myforf.popData();
|
||||
myforf.datastack.push(val);
|
||||
myforf.datastack.push(val);
|
||||
};
|
||||
this.builtins["pop"] = function(myforf) {
|
||||
myforf.datastack.pop();
|
||||
myforf.popData();
|
||||
};
|
||||
this.builtins["exch"] = function(myforf) {
|
||||
var a = myforf.datastack.pop();
|
||||
var b = myforf.datastack.pop();
|
||||
var a = myforf.popData();
|
||||
var b = myforf.popData();
|
||||
myforf.datastack.push(a);
|
||||
myforf.datastack.push(b);
|
||||
};
|
||||
this.builtins["if"] = function(myforf) {
|
||||
var ifclause = myforf.datastack.pop();
|
||||
var cond = myforf.datastack.pop();
|
||||
var ifclause = myforf.popData();
|
||||
var cond = myforf.popData();
|
||||
if (cond) {
|
||||
// TODO: make sure ifclause is a list
|
||||
for (var i = 0; i < ifclause.length; i++) {
|
||||
|
@ -143,9 +141,9 @@ var Forf = function() {
|
|||
}
|
||||
};
|
||||
this.builtins["ifelse"] = function(myforf) {
|
||||
var elseclause = myforf.datastack.pop();
|
||||
var ifclause = myforf.datastack.pop();
|
||||
var cond = myforf.datastack.pop();
|
||||
var elseclause = myforf.popData();
|
||||
var ifclause = myforf.popData();
|
||||
var cond = myforf.popData();
|
||||
if (!cond) {
|
||||
ifclause = elseclause;
|
||||
}
|
||||
|
@ -155,15 +153,15 @@ var Forf = function() {
|
|||
}
|
||||
};
|
||||
this.builtins["mset"] = function(myforf) {
|
||||
var pos = myforf.datastack.pop();
|
||||
var a = myforf.datastack.pop();
|
||||
var pos = myforf.popData();
|
||||
var a = myforf.popData();
|
||||
if (pos < 0 || pos >= MEMORY_SIZE) {
|
||||
throw "invalid memory location";
|
||||
}
|
||||
myforf.mem[pos] = a;
|
||||
};
|
||||
this.builtins["mget"] = function(myforf) {
|
||||
var pos = myforf.datastack.pop();
|
||||
var pos = myforf.popData();
|
||||
if (pos < 0 || pos >= MEMORY_SIZE) {
|
||||
throw "invalid memory location";
|
||||
}
|
||||
|
@ -171,11 +169,20 @@ var Forf = function() {
|
|||
};
|
||||
};
|
||||
|
||||
Forf.prototype.popData = function() {
|
||||
if (this.datastack.length === 0) {
|
||||
throw "tried to pop from empty stack";
|
||||
}
|
||||
return this.datastack.pop();
|
||||
};
|
||||
|
||||
Forf.prototype.init = function(code) {
|
||||
this.code = code;
|
||||
};
|
||||
|
||||
Forf.prototype.parse = function() {
|
||||
this.cmdstack = [];
|
||||
|
||||
// 'parse' the input
|
||||
this.code = this.code.replace(/\([^)]*\)/g, "");
|
||||
var splitCode = this.code.split(/([{}])/).join(" ");
|
||||
|
@ -214,6 +221,8 @@ Forf.prototype.parse = function() {
|
|||
};
|
||||
|
||||
Forf.prototype.run = function() {
|
||||
this.datastack = [];
|
||||
|
||||
var running = true;
|
||||
while (running && this.cmdstack.length) {
|
||||
var val = this.cmdstack.pop();
|
||||
|
@ -222,7 +231,7 @@ Forf.prototype.run = function() {
|
|||
if (val in this.builtins) {
|
||||
func(this);
|
||||
} else {
|
||||
throw "no such function " + val;
|
||||
throw "no such function '" + val + "'";
|
||||
}
|
||||
} else {
|
||||
this.datastack.push(val);
|
||||
|
@ -258,12 +267,12 @@ var ForfTank = function() {
|
|||
myforf.fire();
|
||||
};
|
||||
this.builtins["set-speed!"] = function(myforf) {
|
||||
var right = myforf.datastack.pop();
|
||||
var left = myforf.datastack.pop();
|
||||
var right = myforf.popData();
|
||||
var left = myforf.popData();
|
||||
myforf.setSpeed(left, right);
|
||||
};
|
||||
this.builtins["set-turret!"] = function(myforf) {
|
||||
var angle = myforf.datastack.pop();
|
||||
var angle = myforf.popData();
|
||||
myforf.setTurret(deg2rad(angle));
|
||||
};
|
||||
this.builtins["get-turret"] = function(myforf) {
|
||||
|
@ -271,15 +280,15 @@ var ForfTank = function() {
|
|||
myforf.datastack.push(rad2deg(angle));
|
||||
};
|
||||
this.builtins["sensor?"] = function(myforf) {
|
||||
var sensor_num = myforf.datastack.pop();
|
||||
var sensor_num = myforf.popData();
|
||||
myforf.datastack.push(myforf.getSensor(sensor_num));
|
||||
};
|
||||
this.builtins["set-led!"] = function(myforf) {
|
||||
var active = myforf.datastack.pop();
|
||||
var active = myforf.popData();
|
||||
myforf.setLed(active);
|
||||
};
|
||||
this.builtins["random"] = function(myforf) {
|
||||
var max = myforf.datastack.pop();
|
||||
var max = myforf.popData();
|
||||
if (max < 1) {
|
||||
myforf.datastack.push(0);
|
||||
return;
|
||||
|
@ -658,12 +667,25 @@ var updateTanks = function(tanks) {
|
|||
}
|
||||
|
||||
/* Run programs */
|
||||
var errors = [];
|
||||
for (var i = 0; i < tanks.length; i++) {
|
||||
if (tanks[i].killer) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
tanks[i].parse(tanks[i].code);
|
||||
tanks[i].run();
|
||||
} catch (e) {
|
||||
errors.push(e);
|
||||
}
|
||||
}
|
||||
if (errors.length) {
|
||||
if (interval) {
|
||||
clearInterval(interval);
|
||||
}
|
||||
|
||||
document.getElementById('debug').innerHTML = "Error: " + errors.join();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Fire cannons and check for crashes */
|
||||
|
@ -696,6 +718,8 @@ var resetTanks = function() {
|
|||
clearInterval(interval);
|
||||
}
|
||||
|
||||
document.getElementById('debug').innerHTML = " ";
|
||||
|
||||
tanks = [];
|
||||
ftanks = [];
|
||||
var tank;
|
||||
|
|
|
@ -36,6 +36,9 @@ cat <<EOF >$fn
|
|||
<html>
|
||||
<head>
|
||||
<title>Tanks Round $next</title>
|
||||
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.0/themes/ui-darkness/jquery-ui.css" type="text/css">
|
||||
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
|
||||
<script src="//code.jquery.com/ui/1.11.0/jquery-ui.min.js"></script>
|
||||
<script type="application/javascript" src="tanks.js"></script>
|
||||
<link rel="stylesheet" href="style.css" type="text/css">
|
||||
<script type="application/javascript">
|
||||
|
|
|
@ -191,3 +191,10 @@ table.pollster thead {
|
|||
.swatch {
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.ui-slider-tick-mark {
|
||||
display: inline-block;
|
||||
width: 2px;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ BEGIN {
|
|||
print " <h2>Rankings</h2>";
|
||||
print " <p>Over the last " ngames" games only.</p>";
|
||||
print " <ol>";
|
||||
for (i = rounds - ngames - 1; i < rounds; i += 1) {
|
||||
for (i = rounds - ngames - 1; i > 0 && i < rounds; i += 1) {
|
||||
fn = sprintf("round-%04d.html", i)
|
||||
while (getline < fn) {
|
||||
if ($2 == "score") {
|
||||
|
|
98
tanks.js
98
tanks.js
|
@ -62,11 +62,7 @@ function Tank(ctx, width, height, color, sensors) {
|
|||
if (!this.dead) {
|
||||
return;
|
||||
}
|
||||
if (this.fire == 5) {
|
||||
// one frame of cannon fire
|
||||
this.draw_cannon();
|
||||
this.fire = 0;
|
||||
}
|
||||
|
||||
var points = 7;
|
||||
var angle = Math.PI / points;
|
||||
|
||||
|
@ -74,6 +70,15 @@ function Tank(ctx, width, height, color, sensors) {
|
|||
ctx.translate(this.x, this.y);
|
||||
ctx.rotate(this.rotation);
|
||||
|
||||
if (this.fire == 5) {
|
||||
ctx.save();
|
||||
ctx.rotate(this.turret);
|
||||
// one frame of cannon fire
|
||||
this.draw_cannon();
|
||||
this.fire = 0;
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
ctx.lineWidth = 2;
|
||||
ctx.strokeStyle = craterStroke;
|
||||
ctx.fillStyle = craterFill;
|
||||
|
@ -173,10 +178,21 @@ function Tank(ctx, width, height, color, sensors) {
|
|||
}
|
||||
}
|
||||
|
||||
var loop_id;
|
||||
var updateFunc = null;
|
||||
function togglePlayback() {
|
||||
if ($("#playing").prop("checked")) {
|
||||
loop_id = setInterval(updateFunc, 66);
|
||||
} else {
|
||||
clearInterval(loop_id);
|
||||
loop_id = null;
|
||||
}
|
||||
$("#pauselabel").toggleClass("ui-icon-play ui-icon-pause");
|
||||
}
|
||||
|
||||
function start(id, game) {
|
||||
var canvas = document.getElementById(id);
|
||||
var ctx = canvas.getContext('2d');
|
||||
var loop_id;
|
||||
|
||||
canvas.width = game[0][0];
|
||||
canvas.height = game[0][1];
|
||||
|
@ -199,15 +215,7 @@ function start(id, game) {
|
|||
lastframe = frame;
|
||||
}
|
||||
|
||||
function update() {
|
||||
var idx = frame % (turns.length + 20);
|
||||
var turn;
|
||||
|
||||
frame += 1;
|
||||
if (idx >= turns.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
function drawFrame(idx) {
|
||||
canvas.width = canvas.width;
|
||||
turn = turns[idx];
|
||||
|
||||
|
@ -231,12 +239,72 @@ function start(id, game) {
|
|||
for (i in turn) {
|
||||
tanks[i].draw_tank()
|
||||
}
|
||||
|
||||
document.getElementById('frameid').innerHTML = idx;
|
||||
}
|
||||
|
||||
function update() {
|
||||
var idx = frame % (turns.length + 20);
|
||||
var turn;
|
||||
|
||||
frame += 1;
|
||||
if (idx >= turns.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
drawFrame(idx);
|
||||
|
||||
$('#seekslider').slider('value', idx);
|
||||
}
|
||||
|
||||
function seekToFrame(newidx) {
|
||||
var idx = frame % (turns.length + 20);
|
||||
if (idx !== newidx) {
|
||||
frame = newidx;
|
||||
drawFrame(newidx);
|
||||
}
|
||||
// make sure we're paused
|
||||
if ($("#playing").prop("checked")) {
|
||||
$("#playing").prop("checked", false);
|
||||
togglePlayback();
|
||||
}
|
||||
}
|
||||
|
||||
updateFunc = update;
|
||||
loop_id = setInterval(update, 66);
|
||||
//loop_id = setInterval(update, 400);
|
||||
if (fps) {
|
||||
setInterval(update_fps, 1000);
|
||||
}
|
||||
|
||||
if (id === "battlefield") {
|
||||
$("#game_box").append('<p><input type="checkbox" checked id="playing" onclick="togglePlayback();"><label for="playing"><span class="ui-icon ui-icon-pause" id="pauselabel"></class></label> <span id="frameid">0</span> <span id="seekslider" style="width: 75%; float: right;"></span></p>');
|
||||
$('#playing').button();
|
||||
var slider = $('#seekslider');
|
||||
slider.slider({ max: turns.length-1, slide: function(event, ui) { seekToFrame(ui.value); } });
|
||||
|
||||
var spacing = 100 / turns.length;
|
||||
var deaths = [];
|
||||
for (i in turns[0]) {
|
||||
deaths.push(false);
|
||||
}
|
||||
var percent = 0;
|
||||
for (var f = 0; f < turns.length; f++) {
|
||||
var turn = turns[f];
|
||||
if (percent < (spacing * f)) {
|
||||
percent = spacing * f;
|
||||
}
|
||||
for (var i = 0; i < turn.length; i++) {
|
||||
if (deaths[i]) { continue; }
|
||||
if (!turn[i] || (turn[i][4] & 4)) {
|
||||
deaths[i] = true;
|
||||
// http://stackoverflow.com/questions/8648963/add-tick-marks-to-jquery-slider
|
||||
$('<span class="ui-slider-tick-mark"></span>').css('left', percent + '%').css('background-color', game[1][i][0]).appendTo(slider);
|
||||
percent++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue