-
Notifications
You must be signed in to change notification settings - Fork 0
/
README.txt
170 lines (138 loc) · 7.25 KB
/
README.txt
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
------------
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.