Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
*~
*#
*.o
*.swp

round-*.html
results-*.txt
next-round
points
forftanks
Expand All @@ -14,3 +16,5 @@ summary.html
designer.html
intro.html
procs.html
chord.html
killmatrix.js
57 changes: 40 additions & 17 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,32 +1,55 @@
BINARIES = forftanks designer.cgi
HTML = forf.html procs.html intro.html designer.html
HTML = forf.html procs.html intro.html designer.html chord.html
WWW = style.css grunge.png designer.js figures.js tanks.js nav.html.inc
SCRIPTS = killmatrix.pl rank.awk summary.awk winner.awk

CFLAGS = -Wall
CFLAGS = -Wall -std=gnu90 -g

all: $(BINARIES) $(HTML)

install:
install -d $(DESTDIR)/usr/bin
install run-tanks $(DESTDIR)/usr/bin
install forftanks $(DESTDIR)/usr/bin
forftanks: forftanks.o ctanks.o forf.o tankdir.o tankjson.o
forftanks: LDLIBS = -lm -ljansson

install -d $(DESTDIR)/usr/lib/tanks
install designer.cgi $(DESTDIR)/usr/lib/tanks
install $(HTML) $(DESTDIR)/usr/lib/tanks
install $(WWW) $(DESTDIR)/usr/lib/tanks
cp -r examples $(DESTDIR)/usr/lib/tanks/examples

forftanks: forftanks.o ctanks.o forf.o
forftanks: LDFLAGS = -lm

forftanks.o: forf.h ctanks.h
forftanks.o: forf.h ctanks.h tankdef.h tankdir.h tankjson.h
forf.o: forf.c forf.h
ctanks.o: ctanks.h
tankdir.o: tankdef.h tankdir.h
tankjson.o: tankdef.h tankjson.h

%.html: %.html.m4
m4 $< > $@

.PHONY: install clean check-env
install: check-env
install -d $(DESTDIR)/bin
install run-tanks $(DESTDIR)/bin
install forftanks $(DESTDIR)/bin
install $(SCRIPTS) $(DESTDIR)/bin
install -d $(DOCROOT)
install designer.cgi $(CGIBIN)
install $(HTML) $(DOCROOT)
install $(WWW) $(DOCROOT)
cp -r examples $(DOCROOT)/examples

clean:
rm -f *.o next-round round-*.html
rm -f *.o next-round round-*.html round-*.json results-*.txt current.html
rm -f $(BINARIES) $(HTML)

check-env:
ifndef DESTDIR
$(error DESTDIR is undefined)
endif
ifndef DOCROOT
ifndef DESTDIR
$(error DOCROOT is undefined)
else
DOCROOT = $(DESTDIR)
endif
endif
ifndef CGIBIN
ifndef DESTDIR
$(error CGIBIN is undefined)
else
CGIBIN = $(DESTDIR)
endif
endif
2 changes: 1 addition & 1 deletion README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ hodgepodge of C, Bourne shell, and awk, but at least each piece is
fairly simple to audit.


### round.sh tank1 tank2 ...
### run-tanks tank1 tank2 ...

Runs a single round, awards points with rank.awk, and creates a new
summary.html with summary.awk. This is the main interface that you want
Expand Down
113 changes: 113 additions & 0 deletions chord.html.m4
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="style.css" type="text/css">
<style>
.chord path {
fill-opacity: .67;
stroke: #000;
stroke-width: .5px;
}
text {
color: #FFF;
}
</style>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="killmatrix.js"></script>
</head>
<body>
<h1>Killer Chart</h1>
include(nav.html.inc)
</body>
<script>

var chord = d3.layout.chord()
.padding(.05)
.sortSubgroups(d3.descending)
.matrix(matrix);

var width = 960,
height = 960,
innerRadius = Math.min(width, height) * .31,
outerRadius = innerRadius * 1.1;

var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

svg.append("g").selectAll("path")
.data(chord.groups)
.enter().append("path")
.style("fill", function(d) { return colors[d.index]; })
.style("stroke", function(d) { return colors[d.index]; })
.attr("d", d3.svg.arc().innerRadius(innerRadius).outerRadius(outerRadius))
.on("mouseover", fade(.1))
.on("mouseout", fade(1));

svg.append("g").selectAll("path")
.data(chord.groups)
.enter()
.append("text")
.attr("transform", function(d) { return "rotate("+(-90+(d.startAngle+d.endAngle)*180 / 3.1415 /2)+")translate("+(outerRadius+30)+")";} )
.text(function(d) { return names[ d.index ] } )
.style("fill", "#FFF");

var ticks = svg.append("g").selectAll("g")
.data(chord.groups)
.enter().append("g").selectAll("g")
.data(groupTicks)
.enter().append("g")
.attr("transform", function(d) {
return "rotate(" + (d.angle * 180 / Math.PI - 90) + ")"
+ "translate(" + outerRadius + ",0)";
});

ticks.append("line")
.attr("x1", 1)
.attr("y1", 0)
.attr("x2", 5)
.attr("y2", 0)
.style("stroke", "#FFF");

ticks.append("text")
.attr("x", 8)
.attr("dy", ".35em")
.attr("transform", function(d) { return d.angle > Math.PI ? "rotate(180)translate(-16)" : null; })
.style("text-anchor", function(d) { return d.angle > Math.PI ? "end" : null; })
.text(function(d) { return d.label; })
.style("fill", "#FFF");

svg.append("g")
.attr("class", "chord")
.selectAll("path")
.data(chord.chords)
.enter().append("path")
.attr("d", d3.svg.chord().radius(innerRadius))
.style("fill", function(d) { return colors[d.source.index]; })
.style("opacity", 1);
// Returns an array of tick angles and labels, given a group.
function groupTicks(d) {
var k = (d.endAngle - d.startAngle) / d.value;
return d3.range(0, d.value, 1000).map(function(v, i) {
return {
angle: v * k + d.startAngle,
label: i % 5 ? null : v / 1000 + "k"
};
});
}

// Returns an event handler for fading a given chord group.
function fade(opacity) {
return function(g, i) {
svg.selectAll(".chord path")
.filter(function(d) { return d.source.index != i && d.target.index != i; })
.transition()
.style("opacity", opacity);
};
}

</script>
</html>
54 changes: 36 additions & 18 deletions ctanks.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,17 +105,13 @@ rotate_point(float angle, float point[2])
point[1] = new[1];
}


static void
tanks_fire_cannon(struct tanks_game *game,
struct tank *this,
struct tank *that,
float vector[2],
float dist2)
tanks_collision_detect(struct tanks_game *game,
struct tank *this,
struct tank *that,
float vector[2],
float dist2)
{
float theta = this->angle + this->turret.current;
float rpos[2];

/* If someone's a crater, this is easy */
if (this->killer || that->killer) {
return;
Expand All @@ -128,29 +124,40 @@ tanks_fire_cannon(struct tanks_game *game,

that->killer = this;
that->cause_death = "collision";
}
}

return;
static int
tanks_fire_cannon(struct tanks_game *game,
struct tank *this,
struct tank *that,
float vector[2],
float dist2)
{
float theta = this->angle + this->turret.current;
float rpos[2];

/* If someone's a crater, this is easy */
if (this->killer || that->killer) {
return 0;
}

/* No need to check if it's not even firing */
if (! this->turret.firing) {
return;
return 0;
}

/* Also no need to check if it's outside cannon range */
if (dist2 > TANK_CANNON_ADJ2) {
return;
return 0;
}

/* Did this shoot that? Rotate point by turret degrees, and if |y| <
TANK_RADIUS, we have a hit. */
rpos[0] = vector[0];
rpos[1] = vector[1];
rotate_point(-theta, rpos);
if ((rpos[0] > 0) && (fabsf(rpos[1]) < TANK_RADIUS)) {
that->killer = this;
that->cause_death = "shot";
}
return ((rpos[0] > 0) && (fabsf(rpos[1]) < TANK_RADIUS));
}

static void
Expand Down Expand Up @@ -428,10 +435,21 @@ tanks_run_turn(struct tanks_game *game, struct tank *tanks, int ntanks)
struct tank *that = &tanks[j];

compute_vector(game, vector, &dist2, this, that);
tanks_fire_cannon(game, this, that, vector, dist2);
tanks_collision_detect(game, that, this, vector, dist2);
int a,b;
a = tanks_fire_cannon(game, this, that, vector, dist2);
vector[0] = -vector[0];
vector[1] = -vector[1];
tanks_fire_cannon(game, that, this, vector, dist2);
b = tanks_fire_cannon(game, that, this, vector, dist2);

if(a){
that->killer = this;
that->cause_death = "shot";
}
if(b){
this->killer = that;
this->cause_death = "shot";
}
}
}
}
Loading