Skip to content

Commit acf2145

Browse files
committed
init
0 parents  commit acf2145

File tree

338 files changed

+7758
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

338 files changed

+7758
-0
lines changed

.DS_Store

6 KB
Binary file not shown.

README.md

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Snake Game with AI Bot
2+
3+
![Title Image](./assets/titleimage.png)
4+
5+
This project is a multiplayer browser-based Snake game that utilizes artificial intelligence to train bots to play the game through the application of deep reinforcement learning. The web client is built utilizing the legacy version of Svelte JS and the game server is constructed using the Golang programming language. The bots are trained using the stable baselines 3 library in Python.
6+
7+
## Overview
8+
9+
This project is comprised of three primary components:
10+
11+
- The web client, which is responsible for rendering the game interface for players.
12+
- The game server, which handles the game logic and facilitates communication between clients.
13+
- The training script, which employs deep reinforcement learning to train the bots to play the game.
14+
15+
![Overview](./assets/gamearchitecture.png)
16+
17+
## Technologies
18+
19+
- Web client: Svelte JS (legacy version) - HTML, CSS, Typescript, Tailwind, Svelte, Canvas Rendering
20+
- Game server: Golang
21+
- Training and Testing script: Python, Stable Baselines 3 (DQNs, ...)
22+
23+
## How to run
24+
25+
To run the project, perform the following steps after cloning the repository:
26+
27+
1. Start the game server: ./server/app
28+
2. Start the web client: cd web && npm run dev
29+
3. Start the training script: cd core && python runai.py (Refer to the python file for further instructions); To stop the AI from playing, edit ./core/RUN.txt to any value other than "OK".
30+
31+
## How to play
32+
33+
To play the game, navigate to the URL displayed in the terminal after starting the web client. Enter a nickname and join the game. If the AI script is running, other players will be present to play against.
Binary file not shown.

assets/aitrained.png

202 KB
Loading

assets/gamearchitecture.png

201 KB
Loading

assets/titleimage.png

56.5 KB
Loading

base/saved/README.md

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Quick note:
2+
3+
This is a 256x256 DQN model. This is my second best model, my best one (512x512) was lost due to hardware failure. Feel free to train your own model.

base/saved/dqn_best.zip

1.2 MB
Binary file not shown.

base/saved/nrom_for_dqn_best.pkl

5.88 KB
Binary file not shown.

base/src/__init__.py

Whitespace-only changes.
183 Bytes
Binary file not shown.
1.95 KB
Binary file not shown.
13 KB
Binary file not shown.

base/src/extracted.py

+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import random
2+
import numba as nb
3+
from numba import njit
4+
import numpy as np
5+
6+
7+
# ========== BaseGame ==========
8+
9+
10+
@njit
11+
def obs_v1(distance, fields, direction):
12+
rowlength = 2 * distance + 1
13+
dirvector = np.full(shape=(rowlength,), fill_value=direction)
14+
obs = np.vstack([fields, dirvector])
15+
return obs
16+
17+
18+
@njit
19+
def obs_v2(obs: np.ndarray, direction: int, distance: int):
20+
rowlength = 2 * distance + 1
21+
dirvector = np.full(shape=(rowlength,), fill_value=direction)
22+
23+
# Given a observation for a single frame, make arrays for 8 direction from center
24+
center_x = distance
25+
center_y = distance
26+
27+
# Reverse order where needed so that snake head is always at left side
28+
left_side_arr = obs[center_y][:center_x][::-1]
29+
right_side_arr = obs[center_y][center_x + 1 :]
30+
# up is column above center
31+
up_side_arr = obs[:center_y, center_x][::-1]
32+
# down is column below center
33+
down_side_arr = obs[center_y + 1 :, center_x]
34+
# Now get the diagonals
35+
36+
# top_left_to_bottom_right = obs.diagonal()
37+
# top_right_to_bottom_left = np.fliplr(obs).diagonal()
38+
top_left_to_bottom_right = np.diag(obs)
39+
top_right_to_bottom_left = np.diag(np.fliplr(obs))
40+
# Now split into 8 directions
41+
top_left_side_arr = top_left_to_bottom_right[:center_y][::-1]
42+
bottom_right_side_arr = top_left_to_bottom_right[center_y + 1 :]
43+
top_right_side_arr = top_right_to_bottom_left[:center_y][::-1]
44+
bottom_left_side_arr = top_right_to_bottom_left[center_y + 1 :]
45+
46+
# [element, distance]
47+
left_side = [0, distance]
48+
right_side = [0, distance]
49+
up_side = [0, distance]
50+
down_side = [0, distance]
51+
top_left_side = [0, distance]
52+
bottom_right_side = [0, distance]
53+
top_right_side = [0, distance]
54+
bottom_left_side = [0, distance]
55+
# Now check distance to non zero element from left to right. If only zeros then set to length of array. Add element type to array as first element and distance to that element as second element
56+
for i in range(len(left_side_arr)):
57+
if left_side_arr[i] != 0:
58+
left_side = [left_side_arr[i], i + 1]
59+
break
60+
for i in range(len(right_side_arr)):
61+
if right_side_arr[i] != 0:
62+
right_side = [right_side_arr[i], i + 1]
63+
break
64+
for i in range(len(up_side_arr)):
65+
if up_side_arr[i] != 0:
66+
up_side = [up_side_arr[i], i + 1]
67+
break
68+
for i in range(len(down_side_arr)):
69+
if down_side_arr[i] != 0:
70+
down_side = [down_side_arr[i], i + 1]
71+
break
72+
for i in range(len(top_left_side_arr)):
73+
if top_left_side_arr[i] != 0:
74+
top_left_side = [top_left_side_arr[i], i + 1]
75+
break
76+
for i in range(len(bottom_right_side_arr)):
77+
if bottom_right_side_arr[i] != 0:
78+
bottom_right_side = [bottom_right_side_arr[i], i + 1]
79+
break
80+
for i in range(len(top_right_side_arr)):
81+
if top_right_side_arr[i] != 0:
82+
top_right_side = [top_right_side_arr[i], i + 1]
83+
break
84+
for i in range(len(bottom_left_side_arr)):
85+
if bottom_left_side_arr[i] != 0:
86+
bottom_left_side = [bottom_left_side_arr[i], i + 1]
87+
break
88+
# Now add all the arrays to a list and add direction and return
89+
return np.array(
90+
[
91+
left_side,
92+
right_side,
93+
up_side,
94+
down_side,
95+
top_left_side,
96+
bottom_right_side,
97+
top_right_side,
98+
bottom_left_side,
99+
[direction, direction],
100+
]
101+
)

0 commit comments

Comments
 (0)