forked from mdavolio/mancala
-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.py
136 lines (104 loc) · 3.61 KB
/
server.py
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
125
126
127
128
129
130
131
132
133
134
135
136
# -*- coding: utf-8 -*-
"""
Flask Server for Mancala games
"""
import datetime
import os
from flask import Flask, jsonify
from flask import send_from_directory
from mancala.utility import split_string
from mancala.game import Game
from mancala.agents.random import AgentRandom
from mancala.agents.max import AgentMax
from mancala.agents.max_min import AgentMinMax
from mancala.agents.exact import AgentExact
# Create an A3C Agent if pytorch is available in any form
try:
import torch
from mancala.agents.a3c import AgentA3C
dtype = torch.cuda.FloatTensor if torch.cuda.is_available() else torch.FloatTensor
AGENT_A3C = AgentA3C(os.path.join("models", "a3c.model"), dtype, 454)
except ImportError:
AGENT_A3C = None
except:
print("Unable to load A3C")
AGENT_A3C = None
FLASKAPP = Flask(__name__)
FLASKAPP.config.from_object(__name__)
# Define agents
AGENT_RANDOM = AgentRandom(454)
AGENT_MAX = AgentMax(454)
AGENT_MINNY = AgentMinMax(454, 3)
AGENT_EXACT = AgentExact(454)
def board_str_to_game(board, player_turn):
"""Turns parameters into game or error tuple"""
board_arr = split_string(board, 2)
if len(board_arr) != 14:
return jsonify({"error": "Invalid Board"}), 400
if player_turn != 1 and player_turn != 2:
return jsonify({"error": "Invalid Player"}), 400
game = Game(board_arr, player_turn)
return game
def agent_play(game, agent_str):
"""Play a game, based on agent string. Or no move."""
if agent_str == "random":
game.move(AGENT_RANDOM.move(game))
elif agent_str == 'max':
game.move(AGENT_MAX.move(game))
elif agent_str == 'min_max':
game.move(AGENT_MINNY.move(game))
elif agent_str == 'exact':
game.move(AGENT_EXACT.move(game))
return game
@FLASKAPP.route('/time')
def time():
"""Returns current time"""
return jsonify({'current_time': datetime.datetime.utcnow().isoformat()})
@FLASKAPP.route('/agents')
def agents():
"""Returns available agent strings"""
agents = ['random', 'max', 'min_max', 'exact']
if AGENT_A3C is not None:
agents.append('a3c')
return jsonify({'agents': agents})
@FLASKAPP.route('/play/<string:board>/<int:player_turn>/<int:move>')
def play_board(board, player_turn, move):
"""Make a move based on a player and a board"""
if move < 0 or move > 13:
return jsonify({"error": "Invalid move"}), 400
game = board_str_to_game(board, player_turn)
if not isinstance(game, Game):
return game
game.move(move)
return jsonify({
'board': game.board(),
'player_turn': game.turn_player(),
'score': game.score(),
'game_over': game.over(),
'current_time': datetime.datetime.utcnow().isoformat()
})
@FLASKAPP.route('/agent/<string:board>/<int:player_turn>/<string:agent>')
def play_agent(board, player_turn, agent):
"""Make a move based on a player and a board"""
game = board_str_to_game(board, player_turn)
if not isinstance(game, Game):
return game
game = agent_play(game, agent)
return jsonify({
'board': game.board(),
'player_turn': game.turn_player(),
'score': game.score(),
'game_over': game.over(),
'current_time': datetime.datetime.utcnow().isoformat()
})
@FLASKAPP.route('/')
def serve_index():
"""Serve index"""
full_path = os.path.join(os.getcwd(), 'www')
return send_from_directory(full_path, 'index.html')
@FLASKAPP.route('/<path:filename>')
def serve_static(filename):
"""Serve static files"""
full_path = os.path.join(os.getcwd(), 'www')
return send_from_directory(full_path, filename)
FLASKAPP.run()