--- /dev/null
+#include <cmath>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <msp/gl/immediate.h>
+#include <msp/gl/matrix.h>
+#include <msp/gl/texture.h>
+#include <msp/gl/transform.h>
+#include <msp/time/units.h>
+#include "host.h"
+#include "netvis.h"
+
+using namespace std;
+using namespace Msp;
+
+Host::Host(NetVis &nv, unsigned a):
+ netvis(nv),
+ addr(a)
+{
+ in_addr ina;
+ ina.s_addr=htonl(addr);
+ name=inet_ntoa(ina);
+}
+
+void Host::set_position(const Vector2 &p)
+{
+ pos=p;
+}
+
+void Host::add_connection(Connection &)
+{
+}
+
+Connection *Host::get_connection(Host &)
+{
+ return 0;
+}
+
+void Host::tick(const Msp::Time::TimeDelta &td)
+{
+ float dt=td/Msp::Time::sec;
+
+ const map<unsigned, Host *> &hosts=netvis.get_hosts();
+ float fx=-pos.x*0.1;
+ float fy=-pos.y*0.1;
+ for(map<unsigned, Host *>::const_iterator i=hosts.begin(); i!=hosts.end(); ++i)
+ {
+ if(i->second!=this)
+ {
+ const Vector2 &other_pos=i->second->get_position();
+ float dx=other_pos.x-pos.x;
+ float dy=other_pos.y-pos.y;
+ float d2=dx*dx+dy*dy;
+ float d=sqrt(d2);
+
+ unsigned other_addr=i->second->get_address();
+ unsigned matching_bits=0;
+ for(unsigned j=32; (j-- && !((addr^other_addr)>>j));)
+ ++matching_bits;
+
+ float nearness=24-min(matching_bits, 24U);
+ float f=10000.0*(1.0/(60+nearness*15)-1.0/d);
+
+ fx+=dx/d*f;
+ fy+=dy/d*f;
+ }
+ }
+
+ if(fx<-4 || fx>4)
+ pos.x+=fx*dt;
+ if(fy<-4 || fy>4)
+ pos.y+=fy*dt;
+}
+
+void Host::render() const
+{
+ GL::push_matrix();
+ GL::translate(static_cast<int>(pos.x), static_cast<int>(pos.y), 0);
+
+ GL::Immediate imm((GL::COLOR4_UBYTE, GL::VERTEX2));
+ imm.begin(GL::QUADS);
+ imm.color(1.0f, 1.0f, 1.0f, 1.0f);
+ imm.vertex(-5, -5);
+ imm.vertex(5, -5);
+ imm.vertex(5, 5);
+ imm.vertex(-5, 5);
+ imm.end();
+
+ const GL::Font &font=netvis.get_font();
+ GL::translate(-static_cast<int>(font.get_string_width(name)*5), 6, 0);
+ GL::scale_uniform(10);
+ font.draw_string(name);
+ GL::Texture::unbind();
+
+ GL::pop_matrix();
+}