init - add sync and spawning of gliders

This commit is contained in:
qvalentin 2022-04-02 13:04:51 +02:00
parent 331e463592
commit bcb8de9a9c
Signed by: qvalentin
GPG Key ID: C979FA1EAFCABF1C
12 changed files with 135 additions and 30 deletions

View File

@ -14,8 +14,10 @@ class APIRequests:
jsonValue = response.json()
return Member(jsonValue["ip"], jsonValue["port"])
def get_edge(self, target: Member, direction: Direction):
response = requests.get(f"http://{target.ip}:{target.port}/border/{direction.name}")
def get_edge(self, target: Member, direction: Direction,counter:int):
print(f"Getting {direction} edge from {target} with url http://{target.ip}:{target.port}/border/{direction.name}")
response = requests.get(f"http://{target.ip}:{target.port}/border/{direction.name}?counter={counter}")
print(f"Got {direction} edge from {target}")
return response.json()
def toggle_pause(self, neighbour: Member, new_state: bool):

View File

@ -0,0 +1,28 @@
from Code.Communication.Direction import Direction
class EdgeSync:
def __init__(self, current_edges: dict, counter: int):
self.old_edges = {}
self.current_edges = current_edges
self.counter = counter
self.counter_old = counter - 1
def get_edge(self, edg_pos: Direction, counter: int) -> list:
while counter == self.counter + 1:
pass
if counter == self.counter:
return self.current_edges[edg_pos]
elif counter == self.counter_old:
return self.old_edges[edg_pos]
else:
raise ValueError(f"Requested edge for counter {counter}, but having counter {self.counter} ")
def update_edges(self, new_edges, counter: int):
self.counter_old = self.counter
self.counter = counter
self.old_edges = self.current_edges
self.current_edges = new_edges

View File

@ -25,10 +25,9 @@ class Neighbours:
self.neighbours[direction] = member
return self.own_process, True
def get_edge(self, direction: Direction):
def get_edge(self, direction: Direction,counter:int):
if direction in self.neighbours:
print(f"Getting ghost edge from {self.neighbours[direction]}")
return self.api.get_edge(self.neighbours[direction], mirror(direction))
return self.api.get_edge(self.neighbours[direction], mirror(direction),counter)
elif direction == Direction.RIGHT or direction.LEFT:
return [False] * GeneralConfig.fields_amount_y

View File

@ -1,5 +1,6 @@
import json
import re
import urllib.parse
from dataclasses import asdict
from http.server import BaseHTTPRequestHandler
@ -16,19 +17,25 @@ class RequestHandler(BaseHTTPRequestHandler):
print("got Get request")
if self.path == "/":
self.send_response(200, "running")
self.end_headers()
return
elif self.path.startswith("/border/"):
direction = re.findall("/border/(left|right)", self.path, flags=re.IGNORECASE)[0]
cells = self.game_state.field.get_edge(Direction[direction.upper()])
direction = re.findall("/border/(left|right).*", self.path, flags=re.IGNORECASE)[0]
params = urllib.parse.parse_qs(self.path)
counter = int(params[list(params.keys())[0]][0])
print(f"Getting {direction} edge for counter {counter}")
cells = self.game_state.edge_sync.get_edge(Direction[direction.upper()], counter)
print(f"Serving {direction} edge")
self.send_response(200)
self.send_header('Content-Type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps(cells).encode('utf8'))
return
else:
self.send_response(404)
self.end_headers()
return
"""
/connect/right
@ -53,25 +60,30 @@ class RequestHandler(BaseHTTPRequestHandler):
self.send_header('Content-Type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps(asdict(neighbour)).encode('utf8'))
return
else:
self.send_response(307)
self.send_header('Location', f"http://{neighbour.ip}:{neighbour.port}{self.path}")
self.end_headers()
return
elif self.path.startswith("/pause/"):
new_state = re.findall("/pause/(stop|start)", self.path, flags=re.IGNORECASE)[0] == "start"
print(f"pause endpoint {new_state} old state {self.game_state.pause_for_input}")
print(f"pause endpoint {new_state} old state {self.game_state.is_evolving}")
if new_state == self.game_state.pause_for_input:
if new_state == self.game_state.is_evolving:
print("got pause signal but already in the correct state")
self.send_response(200)
self.end_headers()
return
else:
self.send_response(200)
self.game_state.pause_for_input = new_state
self.game_state.is_evolving = new_state
self.neighbours.toggle_pause(new_state)
self.end_headers()
return
else:
self.send_response(404)
self.end_headers()
return

View File

@ -1,10 +1,16 @@
from http.server import HTTPServer
from socketserver import ThreadingMixIn
from Code.Communication.Neighbours import Neighbours
from Code.Communication.RequestHandler import RequestHandler
from Code.UI.PlayingField import GameState
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
""" This class allows to handle requests in separated threads.
No further content needed, don't touch this. """
class Server:
def __init__(self, neighbours: Neighbours,game_state:GameState):
self.server = None
@ -21,6 +27,6 @@ class Server:
RequestHandler.neighbours = self.neighbours
RequestHandler.game_state = self.game_state
print(f"HTTP Server Running on {self.ip}: {self.port}")
self.server = HTTPServer((self.ip, self.port), RequestHandler)
self.server = ThreadedHTTPServer((self.ip, self.port), RequestHandler)
self.server.serve_forever()
print("Stopped server")

View File

@ -11,6 +11,7 @@ class Colors:
WHITE = (255, 255, 255)
GREY = (84, 84, 84)
class Fonts:
pygame.init()
monospace_20 = pygame.font.SysFont("monospace", 20)
@ -32,4 +33,4 @@ class GeneralConfig:
fields_amount_y = math.trunc(height / SquareConfig.height)
fps = 150
window_caption = "GOL"
evolve_speed = 360 # ziemlich slow das updated abhänig davon wie viele mill sec das game seit dem eltzten mal gelaufen ist im schnit sind das so 60
evolve_speed = 360 # ziemlich slow das updated abhängig davon wie viele mill sec das game seit dem letzten mal gelaufen ist im schnitt sind das so 60

View File

@ -1,6 +1,8 @@
from Code.Communication.Direction import Direction
from Code.Config import GeneralConfig, SquareConfig
from Code.UI import Square
from Code.UI.Shape import Shape
from Code.UI.Shapes import Shapes
from Code.UI.Square import Square
@ -10,6 +12,10 @@ class Field:
self.height = GeneralConfig.fields_amount_y + 2
self.field_shift = -10
self.squares = self._creat_squares()
self.shapes = {Shape.VERTICAL_GLIDER: Shapes().creat_vertical_glieder}
def create_shape(self, shape: Shape, start_square_pos):
self.squares = self.shapes[shape](start_square_pos, self.squares)
def _creat_squares(self):
squares = [
@ -27,10 +33,12 @@ class Field:
for y in x:
y.draw(window)
def get_edge(self, edg_pos: Direction) -> list:
edge = {Direction.LEFT: self.get_left_edge(), Direction.RIGHT: self.get_right_edge(),
def get_edges(self) -> dict:
return {Direction.LEFT: self.get_left_edge(), Direction.RIGHT: self.get_right_edge(),
Direction.TOP: self.get_top(), Direction.BOTTOM: self.get_bottom_edge()}
return edge[edg_pos]
def get_edge(self, edg_pos: Direction) -> list:
return self.get_edges()[edg_pos]
def get_top(self):
top_squares = []

View File

@ -1,19 +1,24 @@
import pygame as pygame
from Code.Communication.Direction import Direction
from Code.Communication.EdgeSync import EdgeSync
from Code.Communication.Neighbours import Neighbours
from Code.Config import Fonts
from Code.Config import GeneralConfig, Colors
from Code.GameLogic.Rules import Rules
from Code.UI.Field import Field
from Code.UI.Shape import Shape
class GameState:
def __init__(self, neighbours: Neighbours):
self.neighbours = neighbours
self.counter = 0
self.run = True
self.pause_for_input = False
self.is_evolving = False
self.field = Field()
self.edge_sync = EdgeSync(self.field.get_edges(), self.counter)
self.update_field_events = []
def event_handler(self):
@ -24,8 +29,22 @@ class GameState:
self.update_field_events.append(event)
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
self.pause_for_input = not self.pause_for_input
self.neighbours.toggle_pause(self.pause_for_input)
print(f"Gamestate: set evolving to {not self.is_evolving}")
self.is_evolving = not self.is_evolving
self.neighbours.toggle_pause(self.is_evolving)
if event.key == pygame.K_v:
index_x = 0
index_y = 0
for line in self.field.squares:
index_y += 1
index_x = 0
for square in line:
index_x += 1
if square.rect.collidepoint(pygame.mouse.get_pos()):
self.field.create_shape(Shape.VERTICAL_GLIDER,
(int(index_y ),
int(index_x )))
def update_field_with_input(self, event):
for line in self.field.squares:
@ -40,15 +59,15 @@ class GameState:
def redraw_field(self, window):
window.fill(Colors.BLACK)
self.field.draw_squares(window)
if not self.pause_for_input:
if not self.is_evolving:
label_font = Fonts.monospace_80
label = label_font.render("Pause", 1, Colors.ORANGE)
window.blit(label, (100, 100))
def update_borders(self):
self.field.fill_right_ghost_edge(self.neighbours.get_edge(Direction.RIGHT))
self.field.fill_left_ghost_edge(self.neighbours.get_edge(Direction.LEFT))
self.field.fill_right_ghost_edge(self.neighbours.get_edge(Direction.RIGHT, self.counter))
self.field.fill_left_ghost_edge(self.neighbours.get_edge(Direction.LEFT, self.counter))
self.counter_old = self.counter
def run_game(game_state: GameState):
@ -60,8 +79,9 @@ def run_game(game_state: GameState):
time_elapsed_since_last_action = 0
while game_state.run:
print(f"running {game_state.pause_for_input}")
game_state.event_handler()
print(f"running {game_state.is_evolving}")
for event in game_state.update_field_events:
game_state.update_field_with_input(event)
@ -70,12 +90,13 @@ def run_game(game_state: GameState):
clock.tick(GeneralConfig.fps)
time_elapsed_since_last_action += clock.get_time()
if game_state.pause_for_input:
if game_state.is_evolving:
if time_elapsed_since_last_action > 100:
# start = ti.time()
game_state.update_borders()
game_state.evolve()
game_state.counter = game_state.counter + 1
game_state.edge_sync.update_edges(game_state.field.get_edges(), game_state.counter)
# end = ti.time()
# print(end - start)
time_elapsed_since_last_action = 0 # reset it to 0 so you can count again

5
Code/UI/Shape.py Normal file
View File

@ -0,0 +1,5 @@
from enum import Enum
class Shape(Enum):
VERTICAL_GLIDER = 1

23
Code/UI/Shapes.py Normal file
View File

@ -0,0 +1,23 @@
from Code import Config
class Shapes:
def creat_vertical_glieder(self, start_square_pos: tuple, squares):
points =[(0,0),(1,0),(2,0),(2,1),(1,2)]
if self._check_bounderies((6, 6), start_square_pos, squares):
for point in points:
squares[start_square_pos[0]+point[1]][start_square_pos[1]+point[0]].active = True
return squares
def _creat_shape(self,start_square_pos: tuple, squares):
def _check_bounderies(self, bounderies, start_square_pos: tuple, field):
x_valid = (Config.GeneralConfig.fields_amount_x-2 - start_square_pos[1]) > bounderies[0]
y_valid = (Config.GeneralConfig.fields_amount_y-2 - start_square_pos[1]) > bounderies[1]
return x_valid and y_valid

0
Code/UI/__init__.py Normal file
View File

0
Code/__init__.py Normal file
View File