Skip to content

Commit

Permalink
Merge pull request #19 from alanhdu/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
samm81 committed Sep 19, 2014
2 parents 315cf36 + 80cdeed commit 6dcc726
Show file tree
Hide file tree
Showing 9 changed files with 189 additions and 65 deletions.
95 changes: 67 additions & 28 deletions game.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import division
from collections import namedtuple, deque, defaultdict
from decimal import *

import numpy as np

Expand Down Expand Up @@ -82,13 +83,19 @@ def __init__(self, w=51, h=23, debug=False):
def addPlayer(self, username):
if username in self.players:
raise excpt.UsernameTaken(username)
for player in self.players.itervalues():
player.ammo += 5
self.players[username] = Player(self, username)

def findPlayer(self, pos):
for player in self.players.itervalues():
if player.pos == pos:
return player

def update(self):
# Update player movements
for player in self.players.itervalues():
player.update()

# Update bullet movements
for bullet in self.bullets:
self.arena[bullet.pos] = " "

Expand All @@ -104,10 +111,11 @@ def update(self):
elif self.arena[bullet.pos] == "*":
self.arena[bullet.pos] = " "
elif self.arena[bullet.pos] in "<>v^":
for player in self.players.itervalues():
if player.pos == bullet.pos:
player.hit(bullet.source, "bullet")
break
player = self.findPlayer(bullet.pos)
player.hit(bullet.source, "bullet")
# Update scores
for player in self.players.itervalues():
player.updateScore()

def __str__(self):
height, width = self.arena.shape
Expand Down Expand Up @@ -152,8 +160,9 @@ class Player(object):
def __init__(self, game, name):
self.game = game
self.name = name
self.deaths = 0
self.kills = 0
self.deaths = self.kills = self.currentScore = 0
self.score = Decimal(0)
self.cloak = self.scan = False
self.rebirth()

def rebirth(self, health=10, ammo=15):
Expand All @@ -177,6 +186,9 @@ def rebirth(self, health=10, ammo=15):
self.health = health
self.ammo = ammo

for player in self.game.players.itervalues():
player.ammo += 5

def updateMask(self):
y, x = self.pos
if self.game.arena[self.pos] == "*":
Expand All @@ -197,9 +209,13 @@ def updateMask(self):

mask[y, x] = True

# Expand all masks so you can see the walls
# TODO Make expansion work with edges
# Scan for other player's locations
if self.scan:
for player in self.game.players.itervalues():
if not player.cloak:
mask[player.pos] = True

# Expand all masks so you can see the walls
mask[1:-1, 1:-1] = (mask[:-2, :-2] + mask[:-2, 1:-1] + mask[:-2, 2:] +
mask[1:-1, :-2] + mask[1:-1,1:-1] + mask[1:-1, 2:] +
mask[2:, :-2] + mask[2:, 1:-1] + mask[2:, 2:])
Expand All @@ -223,8 +239,10 @@ def update(self):
self.lastActionTime += 1
self.actions.appendleft( (func, args, kwargs) )
elif func == "turn" and self.lastActionTime >= speed["turn"]:
self.lastActionTime += 1
self.turn(*args, **kwargs)
elif func == "fire" and self.lastActionTime >= speed["fire"]:
self.lastActionTime += 1
self.fire(*args, **kwargs)
else:
self.lastActionTime += 1
Expand All @@ -235,19 +253,22 @@ def move(self, direction):
self.game.arena[self.pos] = ' '
p = move(self.pos, direction)

if self.cloak:
self.ammo -= 0.05
else:
for player in self.game.players.itervalues():
if player.scan and player is not self:
player.ammo -= 0.05

if self.game.inArena(p):
if self.game.arena[p] == " ":
self.pos = p
self.updateMask()
elif self.game.arena[p] in "<>v^": # stabbing
other = None
for player in self.game.players.itervalues():
if player.pos == p:
other = player
break
elif self.game.arena[p] in "<>v^" and direction == self.facing:
# if we're facing someone and move into them, stab
other = self.game.findPlayer(p)
other.hit(self, "stab")


self.game.arena[self.pos] = self.facing

def turn(self, direction):
Expand All @@ -257,14 +278,21 @@ def turn(self, direction):

def fire(self):
pos = move(self.pos, self.facing)
if self.game.inArena(pos) and self.ammo > 0:
bullet = Bullet(pos, self.facing, self)
self.ammo -= 1
if self.game.arena[bullet.pos] == " ":
self.game.bullets.append(bullet)
self.game.arena[bullet.pos] = ":"
elif self.game.arena[bullet.pos] == "*":
self.game.arena[bullet.pos] = " "
if self.game.inArena(pos):
if self.ammo > 0:
bullet = Bullet(pos, self.facing, self)
self.ammo -= 1
if self.game.arena[bullet.pos] == " ":
self.game.bullets.append(bullet)
self.game.arena[bullet.pos] = ":"
elif self.game.arena[bullet.pos] == "*":
self.game.arena[bullet.pos] = " "
elif self.game.arena[bullet.pos] in "v^<>": # Direct hit
other = self.game.findPlayer(bullet.pos)
other.hit(self, "bullet")
else:
self.msg = "You are out of ammo"


def hit(self, src, method):
if method == "bullet":
Expand All @@ -276,13 +304,24 @@ def hit(self, src, method):

self.health -= damage[method]
if self.health <= 0:
self.msg = "{src} killed you".format(src=src.name)
src.msg = "You killed {target}".format(target=self.name)

src.health += 2 #generate health
src.kills += 1
self.deaths += 1

self.currentScore -= 1
src.currentScore += 1

self.game.arena[self.pos] = " "
self.rebirth()

def updateScore(self):
# use Decimal to avoid annoying scores like 0.000000000001
self.score = Decimal('0.998') * self.score + self.currentScore
self.currentScore = 0

def __str__(self):
h, w = self.view.shape
s = "\n".join("".join( self.game.getType(x, y)
Expand All @@ -291,11 +330,11 @@ def __str__(self):
for x in xrange(w))
for y in xrange(h))
return s
def score(self):
return (self.kills + 1) / (self.deaths + 1)

def to_json(self):
d = {"arena": str(self), "ammo": self.ammo, "health": self.health,
"scores": {name: {"kills":player.kills, "deaths":player.deaths}
"scores": {name: {"kills":player.kills, "deaths":player.deaths,
"score":round(player.score, 3)} # 3 decimal points of score
for name, player in self.game.players.iteritems()}}
if self.msg:
d["msg"] = self.msg
Expand Down
24 changes: 23 additions & 1 deletion server.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,18 @@
import custom_exceptions as excpt

app = Flask(__name__)
socketio = SocketIO(app, excpt.exception_handler)
socketio = SocketIO(app)

@socketio.on_error_default
def exception_handler(value):
if isinstance(value, excpt.UserError):
emit("error", str(value))
else:
raise value

m = game.Game()


@app.route("/")
def index(interval=0.05):
@copy_current_request_context
Expand All @@ -37,6 +45,8 @@ def begin(msg):
player = m.players[msg["username"]]
join_room(msg["username"])

socketio.emit("acknowledged", {}, room=msg["username"])

@socketio.on("logoff")
def logoff(msg):
uname = msg["username"]
Expand All @@ -60,5 +70,17 @@ def fire(msg):
user = msg["username"]
m.players[user].queue("fire")

@socketio.on("scan")
def scan(msg):
user = msg["username"]
m.players[user].scan = not m.players[user].scan

@socketio.on("cloak")
def scan(msg):
user = msg["username"]
m.players[user].cloak = not m.players[user].cloak

if __name__ == "__main__":
for path in glob.glob("static/*.coffee"):
subprocess.call(["coffee", "-c", path])
socketio.run(app, port=8080)
54 changes: 32 additions & 22 deletions sockets.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,12 @@
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""


from gevent import monkey
monkey.patch_all()

import os
import sys

from gevent import monkey
monkey.patch_all()

from socketio import socketio_manage
from socketio.server import SocketIOServer
from socketio.namespace import BaseNamespace
Expand All @@ -38,6 +36,7 @@
from werkzeug._internal import _log



class SocketIOMiddleware(object):
def __init__(self, app, socket):
self.app = app
Expand All @@ -58,16 +57,15 @@ def __call__(self, environ, start_response):


class SocketIO(object):
def __init__(self, app=None, exception_handler=None):
def __init__(self, app=None):
if app:
self.init_app(app)
self.messages = {}
self.rooms = {}
self.server = None

self.exception_handler = exception_handler
if exception_handler is not None and not callable(exception_handler):
raise ValueError("exception_handler must be callable")
self.exception_handlers = {}
self.default_exception_handler = None

def init_app(self, app):
app.wsgi_app = SocketIOMiddleware(app, self)
Expand Down Expand Up @@ -149,7 +147,7 @@ def send(self, message, json=False, ns_name=None, callback=None,
return request.namespace.base_send(message, json, callback)
return request.namespace.socket[ns_name].base_send(message, json, callback)

namespaces = {ns_name: GenericNamespace for ns_name in self.messages}
namespaces = dict( (ns_name, GenericNamespace) for ns_name in self.messages)
return namespaces

def _dispatch_message(self, app, namespace, message, args=[]):
Expand Down Expand Up @@ -189,32 +187,45 @@ def _leave_room(self, namespace, room):
return True
return False

def on_message(self, message, handler, ns_name=""):
if ns_name not in self.messages:
self.messages[ns_name] = {}
self.messages[ns_name][message] = handler
def on_message(self, message, handler, namespace=''):
if namespace not in self.messages:
self.messages[namespace] = {}
self.messages[namespace][message] = handler

def on(self, message, ns_name=""):
if self.exception_handler is not None:
def on(self, message, namespace=''):
if namespace in self.exception_handlers or self.default_exception_handler is not None:
def decorator(f):
def func(*args, **kwargs):
try:
f(*args, **kwargs)
except:
print sys.exc_info()
self.exception_handler(*sys.exc_info(), ns_name=ns_name)

self.on_message(message, func, ns_name)
handler = self.exception_handlers.get(namespace,
self.default_exception_handler)
type, value, traceback = sys.exc_info()
handler(value)
self.on_message(message, func, namespace)
return func
else:
def decorator(f):
self.on_message(message, f, ns_name)
self.on_message(message, f, namespace)
return f
return decorator

def on_error(self, namespace=''):
def decorator(exception_handler):
if not callable(exception_handler):
raise ValueError('exception_handler must be callable')
self.exception_handlers[namespace] = exception_handler

return decorator

def on_error_default(self, exception_handler):
if not callable(exception_handler):
raise ValueError('exception_handler must be callable')
self.default_exception_handler = exception_handler

def emit(self, event, *args, **kwargs):
ns_name = kwargs.pop('namespace', "")
ns_name = kwargs.pop('namespace', '')
room = kwargs.pop('room', None)
if room is not None:
for client in self.rooms.get(ns_name, {}).get(room, set()):
Expand Down Expand Up @@ -260,7 +271,6 @@ def run_server():
else:
self.server.serve_forever()


def emit(event, *args, **kwargs):
return request.namespace.emit(event, *args, **kwargs)

Expand Down
2 changes: 1 addition & 1 deletion static/css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ body {

#map {
line-height: 16px;
}
}
Loading

0 comments on commit 6dcc726

Please sign in to comment.