Conclusions and Recommendations

Conclusions and Recommendations

Overall, the development of the Battleship game was good, and it was executed well. The game was able to mimic the true game of Battleship and did not leave out any features of the real game. The networking feature was also a major plus for this Battleship game. It worked very well on the mobile hotspot that was setup, and the two computers interacted very well. One improvement that could be made with the networking is being able to make a server using something like Amazon Web Services so that it has a more stable place to run the networking. Another improvement that could be made to the game is to improve the user interface. Currently the state of the UI is very basic. Creating a nicer looking GUI would be a big improvement to the game.

Game Discussion

Game Discussion

When starting out in this process of game creation, the group originally decided to focus on making a Connect-Four game as the main game. That game was made; however, it had some minor problems with the win condition and other issues. So as a result, the group decided to shift its focus to making a multiplayer Battleship game instead. This game was going to be unique because the two players would be able to connect their computers via mobile hotspot and play the game together. We began working on this project by testing it and making sure it was all working correctly. One of the only real issues the group had with the Battleship game was that it did not check if your boat’s collided with the edge of the board, so a condition had to be added to check for that. Other than that the other adjustments were just making sure the code looked clean when it was ran, and that the UI was easy for the player to use.

Game Pseudocode

Game Pseudocode

Create Empty Board

Set active player to A

Loop:

Print Board

Query user for move

If input invalid:

Continue to next loop iteration

Update Board

If game won:

Print win message Break loop Swap Active player

 

% We use some wierd matrix hacks in the algorithms. They are difficult to explain because they are functional in nature, but are trivial to implement in MATLAB

 

Update Board Algorithm:

Define column = user input

Create binary matrix occupied occupied predicate on board

Define row = height – sum(column)

Set board state a position (row, column) to player color

 

Check for win Algorithm:

Define zeros matrix with size (height + 2, width + 2)

Element wise sum into zeros matrix from board with (occupied & active player) predicate offset by (1, 1)

Define directions = [1, 0], [0, 1], [1, 1], [1, -1]

For each direction:

Define position = [row, column]

Check how many times current direction can be added without finding false state

Sum with last operation with negated direction

If sum > 2:

Player wins

Player looses

 

% An explanation for the 2: We don’t count the current piece, so if 3 or more are found in a direction there are at least four including the current piece.

 

 

 

Software Introduction

Software Introduction

Our game idea as mentioned before is Battleship with networking capabilities. The general concept of the game is the same as regular Battleship except that our game is played in the terminal. A rough idea of how the game works is the players take turns trying to sink the other players boats by guessing coordinates on the game board. The first player to sink all of their opponent’s boats wins. Our networking feature is also a major component of our game. This feature works by having the two players connecting their laptops to a mobile hotspot and connecting to each other via the terminal.

Final Game Code

fprintf('Starting\n');

t1_socket = tcpip('0.0.0.0', 30000, 'NetworkRole', 'server');
t2_socket = tcpip('0.0.0.0', 30002, 'NetworkRole', 'server');

fopen(t1_socket);
fprintf(t1_socket, 'Welcome to Battleship Player 1!\nWaiting for Player 2...\n');
fopen(t2_socket);
fprintf(t2_socket, 'Hello Player 2! Welcome to Battleship!\n');

fprintf(t1_socket, 'Both players connected!');
fprintf(t2_socket, 'Both players connected!');

socks = [t1_socket, t2_socket];

for i = 1:length(socks)
clearSock(socks(i));
end

boards = setupBoards(socks);

[winner_id, boards] = playRound(boards, socks);

while ~winner_id
[winner_id, boardNew] = playRound(boards, socks);
boards = boardNew;
end

for i = 1:length(socks)
clearSock(socks(i));
fprintf(socks(i), 'Player %d Won!\n', winner_id);
fprintf(socks(i), 'Thank you for playing Battleship!\n');
end
fclose(t1_socket);
fclose(t2_socket);

fprintf('Exiting\n');

function [winner_id, boards] = playRound(boards, socks)
fprintf('Starting Round\n');
winner_id = 0;
done = zeros(1, 2);

for p_id = 1:2
clearSock(socks(p_id));
printBoardHidden(socks(p_id),reshape(boards(3 - p_id,:,:),10,10));
fprintf(socks(p_id), 'Hit location: ');
end

hits = [];

while sum(done) < length(done) [p_id,data] = getSomeInput(socks, ~done); [err, coord, vert] = parseCoord(data); if err fprintf(socks(p_id), 'Bad coordinate, try again: '); continue end done(p_id) = 1; hits(size(hits, 1) + 1,1:4) = [3 - p_id, coord(1), coord(2), p_id]; clearSock(socks(p_id)); fprintf(socks(p_id), 'Waiting for other players...\n'); end pause(.1); for i=1:length(socks) clearSock(socks(i)); fprintf(socks(i), 'Round Results:\n\n'); end for i = 1:size(hits,1) current = boards(hits(i,1), hits(i, 2), hits(i,3)); new = current; if current == 1 new = 2; for p_id=1:length(socks) fprintf(socks(p_id), 'Player %d hit Player %d on [%d, %d] !\n', [hits(i,4), hits(i,1), hits(i,2), hits(i,3)]); end else new = 3; end boards(hits(i,1), hits(i, 2), hits(i,3)) = new; end for p_id=1:length(socks) partsLeft = sum(sum(boards(p_id,:,:) == 1)); if partsLeft == 0 winner_id = 3 - p_id; return end end nhits = size(hits,1); pause(2 + nhits * 1); fprintf('Finished Round\n'); end function boards = setupBoards(socks) SHIP_SIZES = [5 4 3 3 2]; boards = zeros(2, 10, 10) + 0; % Delete this later %boards(:,1:3,1) = 1; %return %%%%%%%%%%%%%%%%%%% for p_id = 1:2 printBoard(socks(p_id),reshape(boards(p_id,:,:),10,10)); fprintf(socks(p_id), 'Location of the first ship (Length %d): ', SHIP_SIZES(1)); end ship_places = ones(1, 2); done = zeros(1, 2); while sum(done) < length(done) [p_id,data] = getSomeInput(socks, ~done); [err, coord, vert] = parseCoord(data); if err fprintf(socks(p_id), 'Bad coordinate, try again: '); continue end [err,sBoard] = drawShip(coord, vert, SHIP_SIZES(ship_places(p_id))); if err fprintf(socks(p_id), 'Collides with wall, try again: '); continue end board = reshape(boards(p_id,:,:),10,10); if sum(sum(board & sBoard)) fprintf(socks(p_id), 'Collides with another ship, try again: '); continue end board = board + sBoard; boards(p_id,:,:) = board; if ship_places(p_id) == length(SHIP_SIZES) clearSock(socks(p_id)); fprintf(socks(p_id), 'Board set up!\n'); printBoard(socks(p_id),reshape(boards(p_id,:,:),10,10)); fprintf(socks(p_id), '\nWaiting for other players...\n'); done(p_id) = 1; else clearSock(socks(p_id)); ship_places(p_id) = 1 + ship_places(p_id); printBoard(socks(p_id),reshape(boards(p_id,:,:),10,10)); fprintf(socks(p_id), 'Location of next ship (Length %d): ', SHIP_SIZES(ship_places(p_id))); end end end function clearSock(socket) % Hex values from `true | clear | xxd` data = char([hex2dec('1b'), hex2dec('5b'), hex2dec('48'), hex2dec('1b'), hex2dec('5b'), hex2dec('4a')]); fprintf(socket, '%s', data); end function [err,board] = drawShip(coord, vert, len) err = 1; board = zeros(10); if coord(2 - vert) + len > 11
return
end

while len > 0
board(coord(1), coord(2)) = 1;
coord(2 - vert) = coord(2 - vert) + 1;
len = len - 1;
end

err = 0;
end

function [err, coord, vert] = parseCoord(str)
err = 1;
coord = [-1 -1];
vert = 1;
if length(str) ~= 2
return
end
if str(1) >= 'a' & str(1) <= 'j' vert = 0; str(1) = char(str(1) - ('a' - 'A')); end if str(1) >= 'A' & str(1) <= 'J' coord(1) = str(1) - 'A' + 1; else return end if str(2) >= '0' & str(2) <= '9' coord(2) = str(2) - '0' + 1; else return end err = 0; end function [p_id,data] = getSomeInput(socks, sockmask) p_id = 0; data = ''; while 1 for pid = 1:length(socks) p_id = pid; if ~sockmask(p_id) continue end if socks(p_id).BytesAvailable > 0
data = fread(socks(p_id), socks(p_id).BytesAvailable);
data = data(1:length(data)-1); % Remove newline
fprintf('Got data from %d: [%s]\n', p_id, data);
return
end
end
end
end

function printBoard(socket, board)
width = size(board,2);
line = char(zeros(1,width + 2) + '-');
asciiBoard = char((board == 1) * 'H' + (board == 0) * ' ' + (board == 2) * 'X' + '.' * (board == 3));
fprintf(socket,'%s\n', line);
for i=1:width
fprintf(socket,'|%s|', convertCharsToStrings(asciiBoard(i,:)),'sync');
fprintf(socket,'%s\n', convertCharsToStrings(char('A' + i - 1)), 'sync');
end
fprintf(socket,'%s\n', convertCharsToStrings(line));
fprintf(socket,' %s\n',convertCharsToStrings(char((1:width) + '0' - 1)));
end

function printBoardHidden(socket, board)
width = size(board,2);
line = char(zeros(1,width + 2) + '-');
asciiBoard = char((board == 1) * ' ' + (board == 0) * ' ' + (board == 2) * 'X' + '.' * (board == 3));
fprintf(socket,'%s\n', line);
for i=1:width
fprintf(socket,'|%s|', convertCharsToStrings(asciiBoard(i,:)),'sync');
fprintf(socket,'%s\n', convertCharsToStrings(char('A' + i - 1)), 'sync');
end
fprintf(socket,'%s\n', convertCharsToStrings(line));
fprintf(socket,' %s\n',convertCharsToStrings(char((1:width) + '0' - 1)));
end

Project Schedule/Meeting Notes

Project Schedule/Meeting Notes

October 30th, 2018: Software Design Project Day 1

Work day for initial programming and design, also for working on documentation.

November 6th, 2018: Software Design Project Day 2

Continuing work on the programming and design, also continuing on the documentation.

November 13th, 2018: Software Design Project Day 3

Finishing up programming and design for the first version of the game.

November 27th, 2018: Software Design Project Day 4

Finalized all game code and demonstrated the final game to TA’s.
November 28th, 2018: Software Design Project Video

Group members met to record the segments for the SDP Video and also edit the video.