diff --git a/pyproject.toml b/pyproject.toml
index bb9e713..a04cf1e 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -9,5 +9,6 @@ dependencies = [
"chess==1.10.0",
"numpy==1.26.3",
"stockfish==3.28.0",
+ "aiohttp==3.9.1",
]
requires-python = ">= 3.10"
diff --git a/requirements.txt b/requirements.txt
index b83defa..2e4154a 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,3 +1,4 @@
chess==1.10.0
numpy==1.26.3
-stockfish==3.28.0
\ No newline at end of file
+stockfish==3.28.0
+aiohttp
\ No newline at end of file
diff --git a/src/chesspp/res/bB.png b/src/chesspp/res/bB.png
new file mode 100644
index 0000000..be3007d
Binary files /dev/null and b/src/chesspp/res/bB.png differ
diff --git a/src/chesspp/res/bK.png b/src/chesspp/res/bK.png
new file mode 100644
index 0000000..de9880c
Binary files /dev/null and b/src/chesspp/res/bK.png differ
diff --git a/src/chesspp/res/bN.png b/src/chesspp/res/bN.png
new file mode 100644
index 0000000..e31a6d0
Binary files /dev/null and b/src/chesspp/res/bN.png differ
diff --git a/src/chesspp/res/bP.png b/src/chesspp/res/bP.png
new file mode 100644
index 0000000..afa0c9d
Binary files /dev/null and b/src/chesspp/res/bP.png differ
diff --git a/src/chesspp/res/bQ.png b/src/chesspp/res/bQ.png
new file mode 100644
index 0000000..4649bb8
Binary files /dev/null and b/src/chesspp/res/bQ.png differ
diff --git a/src/chesspp/res/bR.png b/src/chesspp/res/bR.png
new file mode 100644
index 0000000..c7eb127
Binary files /dev/null and b/src/chesspp/res/bR.png differ
diff --git a/src/chesspp/res/index.html b/src/chesspp/res/index.html
new file mode 100644
index 0000000..e73b4fb
--- /dev/null
+++ b/src/chesspp/res/index.html
@@ -0,0 +1,43 @@
+
+
+
+ChessPP
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/chesspp/res/wB.png b/src/chesspp/res/wB.png
new file mode 100644
index 0000000..70e0e14
Binary files /dev/null and b/src/chesspp/res/wB.png differ
diff --git a/src/chesspp/res/wK.png b/src/chesspp/res/wK.png
new file mode 100644
index 0000000..bbf5664
Binary files /dev/null and b/src/chesspp/res/wK.png differ
diff --git a/src/chesspp/res/wN.png b/src/chesspp/res/wN.png
new file mode 100644
index 0000000..237250c
Binary files /dev/null and b/src/chesspp/res/wN.png differ
diff --git a/src/chesspp/res/wP.png b/src/chesspp/res/wP.png
new file mode 100644
index 0000000..5f9315c
Binary files /dev/null and b/src/chesspp/res/wP.png differ
diff --git a/src/chesspp/res/wQ.png b/src/chesspp/res/wQ.png
new file mode 100644
index 0000000..c3dfc15
Binary files /dev/null and b/src/chesspp/res/wQ.png differ
diff --git a/src/chesspp/res/wR.png b/src/chesspp/res/wR.png
new file mode 100644
index 0000000..cc69760
Binary files /dev/null and b/src/chesspp/res/wR.png differ
diff --git a/src/chesspp/web.py b/src/chesspp/web.py
new file mode 100644
index 0000000..e828175
--- /dev/null
+++ b/src/chesspp/web.py
@@ -0,0 +1,79 @@
+import os
+import asyncio
+import aiohttp
+from aiohttp import web
+
+import chess
+from chesspp import engine
+
+_DIR = os.path.abspath(os.path.dirname(__file__))
+_INDEX = os.path.join(_DIR, "res/index.html")
+
+def load_index():
+ with open(_INDEX, 'r') as fp:
+ return fp.read()
+
+
+index_data = load_index()
+
+async def handle_index(request):
+ #raise web.HTTPFound('/index.html')
+ return web.Response(text=load_index(), content_type='text/html')
+
+class Simulate:
+ def __init__(self):
+ self.white = engine.ClassicMctsEngine(chess.WHITE)
+ self.black = engine.ClassicMctsEngine(chess.BLACK)
+
+ def run(self):
+ board = chess.Board()
+
+ is_white_playing = True
+ while not board.is_game_over():
+ play_result = self.white.play(board) if is_white_playing else self.black.play(board)
+ yield play_result.move
+ board.push(play_result.move)
+ is_white_playing = not is_white_playing
+
+
+async def websocket_handler(request):
+ ws = web.WebSocketResponse()
+ await ws.prepare(request)
+
+ async def wait_msg():
+ async for msg in ws:
+ if msg.type == aiohttp.WSMsgType.TEXT:
+ if msg.data == 'close':
+ await ws.close()
+ elif msg.type == aiohttp.WSMsgType.ERROR:
+ print(f'ws connection closed with exception {ws.exception()}')
+
+ async def turns():
+ runner = Simulate().run()
+ def sim():
+ return next(runner, None)
+
+ turn = await asyncio.to_thread(sim)
+ while turn is not None:
+ await ws.send_str(turn.uci())
+ turn = await asyncio.to_thread(sim)
+
+ async with asyncio.TaskGroup() as tg:
+ tg.create_task(wait_msg())
+ tg.create_task(turns())
+
+ print('websocket connection closed')
+
+ return ws
+
+
+app = web.Application()
+app.add_routes([
+ web.get('/', handle_index),
+ #web.static('/', os.path.join(_DIR, 'res')),
+ web.static('/img/chesspieces/wikipedia/', os.path.join(_DIR, 'res')),
+ web.get('/ws', websocket_handler),
+])
+
+if __name__ == '__main__':
+ web.run_app(app)