Skip to content

tlively/distributed-lightcycle

Repository files navigation

------------
Introduction
------------

This code base contains the implementation of a peer-to-peer
LightCycle game. The game is backed by two different network layers
that can be interchanged to see how a naive network layer works in
comparison to one that has consistency as guaranteed by Paxos. The
game must be set up with one computer acting as a centralized
server. After all of the TCP connections are set up, the game operates
in a peer-to-peer system. Network failure can be introduced into the
system to investigate how the naive system and the Paxos system deal
with the loss of packets. Since the system is built on TCP
connections, we are able to ensure that the failure is controlled by
our injected failure, because TCP retries if a send fails.

-------------------------
Overview of the code base
-------------------------

main.py

	This has the main control flow of the game. It handles the
	user input that starts the game, sets up the game window, sets
	up the networking layer, and runs the main game loop.

game_utils.py

	This contains utility functions and classes necessary for
	running the game. The three classes defined in the file are
	Direction, Message and Game State. Direction defines the
	cardinal directions and allows a player to extrapolate in a
	given direction given a location. Message encapsulates the
	inter-client communication. It has multiple Message types that
	can be created and serialized and deserialized for sending
	over the wire via protocol buffers. Game State is an object
	that has the state of the game that each of the players
	holds. It has various information about the state of the board
	and methods for initializing the game and running it. There
	are three other functions in game_utils.py that are used for
	drawing the lines for the game.

network_layers.py

	This has the main NetworkLayer class. This is inherited by the
	RandomNoNetworkLayer, which was used for development of the
	game, the NaiveNetworkLayer, which is the network layer that
	has no agreement algorithm, and PartTimeNetworkLayer, which is
	the network layer that uses Paxos for agreement. The utilities
	that this file uses are defined in player_pb2, paxosmsg_pb2,
	and network_utils (the first two are auto- generated by the
	protocol buffer package--the important part is the protobuf
	structure that creates them, as defined in the .proto files).

network_utils.py

	This contains the utility classes and functions for network
	operations. We defined two different socket types that are
	used in the network layers. These are the SelfLoopSocket and
	WrappedSocket, which are used for getting your own moves and
	getting an individual message. The failure rate is one of the
	arguments to WrappedSocket and can be defined in the
	class. The functions establish_tcp_connections and
	coordinate_tcp_connections are used for the initial setup of
	the TCP connections for the game.

player.proto and paxosmsg.proto

	These are the protocol buffer structures used to create the
	player_pb2.py and paxosmsg_pb2.py, which are used for
	serializing and deserializing messages to send over the wire.

Network Development folder

	This contains the files that we used to figure out how to set
	up the TCP peer-to-peer connections. These files are not used
	in the game but are interesting for seeing the development of
	the later files.

---------------
Starting a game
---------------

The network layer being run is on line 7 of main.py. Modify this if
you wish to switch to a different network layer (described in
network_layers.py). The default is the Paxos network layer
(PartTimeNetworkLayer). Pick one computer to be the one to start the
game as a centralized server. On that computer, run:

	python main.py

This will display the IP address of the computer hosting the
game. Then, in a separate window, possibly on a separate computer if
desired, run:

	python main.py [IP ADDRESS]

This will spin up the other players. 4 instances total are required to
start the game. After all players are connected, you can begin
playing, using the arrow keys or 'w', 'a', 's', 'd' to move.

To change the failure rate of the network, change failprob in the
WrappedSocket class in network_utils.py. It is defined as failprob on
line 31.

------------
Dependencies
------------

Our code base runs on Python 2.7 using PyGame 1.9.1. The Paxos library
is in the repository and the protocol buffer code works with the files
in the repository with no additional package installation necessary.

---------------------------------
Assumptions about the environment
---------------------------------

Our major assumption is that every player in our peer-to-peer game is
reachable by every other player. This requires that everyone have
world-facing IP address or that all players are on the same subnet
without a firewall to block communication among them. We also
currently only support four players, although that could be changed
relatively easily in the bootstrapping code.

----------------------------
Interface between components
----------------------------

Our implementation has three key classes which are used in a main loop
to run the game and handle all communication.

The first class is a game state class. It stores the players current
positions, whether they are alive or dead, and a list of all turns
ever taken (direction and position), which can be used to reconstruct
all walls on the board. It exposes functions to initialize a new
state, to update state if players did not move (move everyone
forward), to update state with a turn, and to kill a player.

The second class is a message class used for all inter-client
communication that is exposed above the level of the network layer. It
exposes serialization and deserialization functions, as well as
functions to create start, move, and kill messages to send to other
players.

The third class is the network layer itself. The interface it exposes
is relatively simple, containing only functions to send messages to
all players and receive messages from all players, as well as a start
function. Underneath these three functions are the naive network layer
or Paxos, depending on implementation. The implementations are built
using a wrapped TCP socket class that lets us consistently and
reproducibly inject error into the networking.

Before the game can begin, the peer-to-peer network has to be
initialized. This is done using one player as a pseudo-server. The
first player to try to enter a game has to give their IP address and
port number to all other players, who then connect to them. The first
player receives connections from all other players and sends
information about them to each other. This bootstrapping process
eventually opens connections between every player and every other
player.

After all players are connected to each other, the game enters the
main loop. In the main loop, the game receives messages (either turn
or kill) from other players and updates the board state (displayed on
the screen using PyGame) with those turns or kills. It also receives
user input and updates the displayed board state with the results of
that input while broadcasting it to other players. Very little real
work is done in the main loop; it consists mostly of input-processing
logic and PyGame display commands. Most of the actual complexity is in
the network layer and the calls to get_messages and broadcast_message.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published