-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.py
More file actions
124 lines (101 loc) · 3.49 KB
/
Copy pathserver.py
File metadata and controls
124 lines (101 loc) · 3.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import socket
import random
import time
import math
from flask import Flask, request
from flask_socketio import SocketIO, join_room, emit
app = Flask(__name__)
app.config['SECRET_KEY'] = 'neural_lock'
socketio = SocketIO(app, cors_allowed_origins="*")
games = {}
@app.route('/')
def index():
with open('index.html', 'r', encoding='utf-8') as f:
return f.read()
def get_local_ip():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
s.connect(('10.255.255.255', 1))
IP = s.getsockname()[0]
except:
IP = '127.0.0.1'
finally:
s.close()
return IP
@socketio.on('join_game')
def on_join(data):
room = data['room']
join_room(room)
if room not in games:
games[room] = {'players': [], 'p1_scores': {}}
if request.sid not in games[room]['players']:
games[room]['players'].append(request.sid)
# Assign Role: First is HOST
role = 'HOST' if len(games[room]['players']) == 1 else 'CHALLENGER'
emit('role_assigned', {'role': role}, to=request.sid)
if len(games[room]['players']) == 2:
# Start Phase 1
games[room]['p1_start'] = time.time()
emit('phase1_start', room=room)
@socketio.on('p1_submit')
def on_p1_submit(data):
# data = {score: int, finished: bool}
room = data['room']
# Record finish time
finish_time = time.time()
duration = finish_time - games[room]['p1_start']
games[room]['p1_scores'][request.sid] = {
'score': data['score'], # Accuracy score
'time': duration
}
# Check if both done
if len(games[room]['p1_scores']) == 2:
calculate_phase2(room)
def calculate_phase2(room):
pids = games[room]['players']
p1 = games[room]['p1_scores'][pids[0]]
p2 = games[room]['p1_scores'][pids[1]]
# Logic: Weighted Score (Accuracy is king, Speed is queen)
# Score formula: (Correct Answers * 1000) - (Seconds * 10)
s1 = (p1['score'] * 1000) - (p1['time'] * 10)
s2 = (p2['score'] * 1000) - (p2['time'] * 10)
winner_idx = 0 if s1 > s2 else 1
time_diff = abs(p1['time'] - p2['time'])
# STRICT PROMPT MATH:
# Bullets = 2 * (seconds faster). Min 4, Max 20 cap for gameplay sanity.
# If speed diff is small but accuracy won, give base 6 bullets.
bullets = max(6, min(24, int(2 * time_diff)))
if time_diff < 1: bullets = 5 # Minimum edge
# Nodes = floor(bullets / 2)
nodes = math.floor(bullets / 2)
attacker = pids[winner_idx]
defender = pids[1 - winner_idx]
emit('phase2_init', {
'attacker': attacker,
'defender': defender,
'bullets': bullets,
'nodes': nodes,
'assist_limit': 3
}, room=room)
# --- BATTLE SYNC ---
@socketio.on('shoot_bullet')
def on_shoot(data):
# Invert Y for defender (Top-Down view swap)
inverted = {
'x': data['x'],
'y': 0, # Force top origin
'vx': data['vx'],
'vy': -data['vy'] # Flip vert velocity
}
emit('enemy_shoot', inverted, room=data['room'], include_self=False)
@socketio.on('move_slider')
def on_slider(data):
# data = {id: 0/1, x: 0.0-1.0}
# Defender moves slider. Attacker sees it.
emit('sync_slider', data, room=data['room'], include_self=False)
@socketio.on('node_hit')
def on_hit(data):
emit('sync_node_destroy', data, room=data['room'], include_self=False)
if __name__ == '__main__':
print(f"\nSERVER RUNNING: http://{get_local_ip()}:5000\n")
socketio.run(app, host='0.0.0.0', port=5000, debug=True)