diff --git a/README.md b/README.md index 06d52f8..631d01f 100644 --- a/README.md +++ b/README.md @@ -57,4 +57,5 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/CAU-Kiel-Tech-Inf/socha_ruby_client. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the -[Contributor Covenant](contributor-covenant.org) code of conduct. +[code of conduct](CODE_OF_CONDUCT.md) (from +[Contributor Covenant](http://contributor-covenant.org)). diff --git a/RELEASES.md b/RELEASES.md index 0d01339..ec6296d 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,10 @@ += 0.1.2 + +- Fixed bug in == (test for equality) method of connections (thanks to + wollw!). +- Fixed link in readme to code of conduct. +- Removed trailing whitespace. + = 0.1.1 Compatibility to Ruby 1.9 (source encoding issues) diff --git a/lib/software_challenge_client/board.rb b/lib/software_challenge_client/board.rb index 5d69ec8..3c01dca 100644 --- a/lib/software_challenge_client/board.rb +++ b/lib/software_challenge_client/board.rb @@ -16,11 +16,11 @@ class Board # @!attribute [r] connections # @return [Array] the board's connections attr_reader :connections - + def initialize self.init end - + # Initializes the board # # @param init [Boolean] if 'true', then the board will be initialized with swamps, otherwise the board will be completely empty @@ -31,9 +31,9 @@ def initialize(init) self.makeClearBoard end end - + # Initializes the board with swamps - def init + def init @fields = Array.new(Constants::SIZE) {Array.new(Constants::SIZE)} @fields[0][0] = Field.new(FieldType::SWAMP, 0, 0) @fields[0][Constants::SIZE - 1] = Field.new(FieldType::SWAMP, 0, Constants::SIZE - 1) @@ -48,14 +48,14 @@ def init @fields[Constants::SIZE - 1][y] = Field.new(FieldType::BLUE, Constants::SIZE - 1, y); end for x in 1..(Constants::SIZE - 2) - for y in 1..(Constants::SIZE - 2) + for y in 1..(Constants::SIZE - 2) @fields[x][y] = Field.new(FieldType::NORMAL, x, y); end end self.placeSwamps() @connections = Array.new; end - + # Places swamps at random coordinates def placeSwamps # big swamp @@ -88,25 +88,25 @@ def placeSwamps self.fields[x][y].type = FieldType::SWAMP end - - # creates a cleared board + + # creates a cleared board def makeClearBoard @fields = Array.new(Constants::SIZE, Array.new(Constants::SIZE)) @connections = Array.new end - + # gets the owner's color for the field at the coordinate (x, y) - # + # # @param x [Integer] x-coordinate # @param y [Integer] y-coordinate # @return [PlayerColor] owner's color of field (x, y) - def getOwnerColor(x, y) + def getOwnerColor(x, y) return self.fields[x][y].ownerColor end - - + + # sets the owner's color for the field at the coordinate (x, y) - # + # # @param x [Integer] x-coordinate # @param y [Integer] y-coordinate # @param player [Player] new owner of field (x, y) @@ -116,7 +116,7 @@ def put(x, y, player) end # creates wires at the coordinate (x, y), if it is possible - # + # # @param x [Integer] x-coordinate # @param y [Integer] y-coordinate def createNewWires(x, y) @@ -144,11 +144,11 @@ def createNewWires(x, y) if self.checkPossibleWire(x, y, x + 1, y + 2) self.createWire(x, y, x + 1, y + 2) end - - end + + end # creates a new wire - # + # # @param x1 [Integer] x-coordinate starting point # @param y1 [Integer] y-coordinate starting point # @param x2 [Integer] x-coordinate ending point @@ -158,7 +158,7 @@ def createWire(x1, y1, x2, y2) end # checks, if a wire can be placed at specified coordinates - # + # # @param x1 [Integer] x-coordinate starting point # @param y1 [Integer] y-coordinate starting point # @param x2 [Integer] x-coordinate ending point @@ -174,7 +174,7 @@ def checkPossibleWire(x1, y1, x2, y2) end # checks, if a blocking wire exists - # + # # @param x1 [Integer] x-coordinate starting point # @param y1 [Integer] y-coordinate starting point # @param x2 [Integer] x-coordinate ending point @@ -187,7 +187,7 @@ def existsBlockingWire(x1, y1, x2, y2) for y in smallerY..biggerY # checks all 6 Fields, from # where there could be # blocking connections - if !self.fields[x][y].ownerColor.nil? && (x != x1 || y != y1) && + if !self.fields[x][y].ownerColor.nil? && (x != x1 || y != y1) && (x != x2 || y != y2) # excludes the Fields with no owner and # the fields (x1, y2), (x2, y2) # themselves. @@ -199,9 +199,9 @@ def existsBlockingWire(x1, y1, x2, y2) end return false end - + # gets connections for the coordinate (x, y) - # + # # @param x [Integer] x-coordinate # @param y [Integer] y-coordinate # @return [Array] Array of connections from field (x, y) @@ -209,7 +209,7 @@ def getConnections(x, y) xyConnections = Array.new if !self.connections.nil? for c in self.connections - if c.x1 == x && c.y1 == y + if c.x1 == x && c.y1 == y xyConnections.push(Connection.new(x, y, c.x2, c.y2, c.ownerColor)) end if c.x2 == x && c.y2 == y @@ -229,11 +229,11 @@ def onSegment(px,py,qx,qy,rx,ry) end return false end - + def orientation(px,py,qx,qy,rx,ry) val = (qy - py) * (rx - qx) - (qx - px) * (ry - qy) - + if val == 0 return 0 end @@ -242,44 +242,44 @@ def orientation(px,py,qx,qy,rx,ry) end return 2 end - + def doIntersect(p1x,p1y, q1x,q1y, p2x,p2y, q2x,q2y) o1 = orientation(p1x,p1y, q1x,q1y, p2x,p2y) o2 = orientation(p1x,p1y, q1x,q1y, q2x,q2y) o3 = orientation(p2x,p2y, q2x,q2y, p1x,p1y) o4 = orientation(p2x,p2y, q2x,q2y, q1x,q1y) - + if o1 != o2 && o3 != o4 return true end - + if o1 == 0 && onSegment(p1x,p1y, p2x,p2y, q1x,q1y) return true end - + if o2 == 0 && onSegment(p1x,p1y, q2x,q2y, q1x,q1y) return true end - + if o3 == 0 && onSegment(p2x,p2x, p1x,p1y, q2x,q2y) return true end - + if o4 == 0 && onSegment(p2x,p2y, q1x,q1y, q2x,q2y) return true end - + return false end # checks for the wire (x1, y1) -> (x2, y2), if it is blocked by any connection going out from (x,y). - # + # # @param x1 [Integer] x-coordinate starting point # @param y1 [Integer] y-coordinate starting point # @param x2 [Integer] x-coordinate ending point # @param y2 [Integer] y-coordinate ending point # @param x [Integer] x-coordinate comparison field - # @param y [Integer] y-coordinate comparison field + # @param y [Integer] y-coordinate comparison field # @return [Boolean] 'true', if another wire would block the creation of a new wire at specified coordinates def isWireBlocked(x1, y1, x2, y2, x, y) for c in getConnections(x, y) @@ -293,7 +293,7 @@ def isWireBlocked(x1, y1, x2, y2, x, y) def to_s return self.fields.map { |f| f.map {|i| (i.ownerColor==PlayerColor::RED ? 'R' : (i.ownerColor==PlayerColor::BLUE ? 'B' : (i.type==FieldType::SWAMP ? 'S' : (i.type==FieldType::RED ? 'r' : (i.type==FieldType::BLUE ? 'b' : ' '))))) }.join(",")}.join("\n") end - + def ==(another_board) for x in 0..(Constants.SIZE - 1) for y in 0..(Constants.SIZE - 1) @@ -310,7 +310,7 @@ def ==(another_board) return false end end - + return true; end end \ No newline at end of file diff --git a/lib/software_challenge_client/client_interface.rb b/lib/software_challenge_client/client_interface.rb index 62b8bde..70749f2 100644 --- a/lib/software_challenge_client/client_interface.rb +++ b/lib/software_challenge_client/client_interface.rb @@ -1,7 +1,7 @@ # encoding: UTF-8 class ClientInterface attr_accessor :gamestate - + def getMove raise "Not yet implemented" end diff --git a/lib/software_challenge_client/condition.rb b/lib/software_challenge_client/condition.rb index be20a82..5d2b7a2 100644 --- a/lib/software_challenge_client/condition.rb +++ b/lib/software_challenge_client/condition.rb @@ -10,7 +10,7 @@ class Condition # @!attribute [r] reason # @return [String] winning reason attr_reader :reason - + # Initializes the winning Condition with a player and a reason # @param winer [Player] winning player # @param reason [String] winning reason @@ -18,5 +18,5 @@ def initialize(winner, reason) @winner = winner @reason = reason end - + end \ No newline at end of file diff --git a/lib/software_challenge_client/connection.rb b/lib/software_challenge_client/connection.rb index b602437..81391eb 100644 --- a/lib/software_challenge_client/connection.rb +++ b/lib/software_challenge_client/connection.rb @@ -19,32 +19,38 @@ class Connection # @!attribute [r] ownerColor # @return [PlayerColor] connection's owner's color attr_reader :ownerColor - + # Initializer - # + # # @param x1 [Integer] x-coordinate starting point # @param y1 [Integer] y-coordinate starting point # @param x2 [Integer] x-coordinate ending point # @param y2 [Integer] y-coordinate ending point # @param owner [PlayerColor] connection's owner's color - def initialize(x1, y1, x2, y2, ownerColor) + def initialize(x1, y1, x2, y2, ownerColor) @x1 = x1 @x2 = x2 @y1 = y1 @y2 = y2 @ownerColor = ownerColor end - + def ==(another_connection) - if(self.x1 == another_connection.x1 && self.y1 == another_connection.y1 && self.x2 == another_connection.x2 && self.y2 == another_connection.y2 || - self.x1 == another_connection.x2 && self.y1 == another_connection.y2 && self.x2 == another_connection.x1 && self.y2 == another_connection.y1) - return ownerColor == c.ownerColor + if (self.x1 == another_connection.x1 && + self.y1 == another_connection.y1 && + self.x2 == another_connection.x2 && + self.y2 == another_connection.y2 || + self.x1 == another_connection.x2 && + self.y1 == another_connection.y2 && + self.x2 == another_connection.x1 && + self.y2 == another_connection.y1) + return ownerColor == another_connection.ownerColor else return false end end - + def to_s return "#{self.ownerColor} : (#{self.x1}, #{self.y1}) - (#{self.x2}, #{self.y2})" end -end \ No newline at end of file +end diff --git a/lib/software_challenge_client/debug_hint.rb b/lib/software_challenge_client/debug_hint.rb index 587cfaf..cd10cde 100644 --- a/lib/software_challenge_client/debug_hint.rb +++ b/lib/software_challenge_client/debug_hint.rb @@ -2,11 +2,11 @@ # @author Ralf-Tobias Diekert # A debug hint, that can be added to a move class DebugHint - + # @!attribute [r] content # @return [String] a hint attr_reader :content - + # @overload initialize # Creates an empty hint # @overload initialize(key, value) @@ -17,17 +17,17 @@ class DebugHint # Creates a hint with specified content # @param content of the hint def initialize - + end - + def initialize(key, value) if key.nil? self.content = "#{value}" - else + else self.content = "#{key} = #{value}" end end - + def initialize(content) self.content = "#{content}" end diff --git a/lib/software_challenge_client/field.rb b/lib/software_challenge_client/field.rb index 7564a86..0c37b11 100644 --- a/lib/software_challenge_client/field.rb +++ b/lib/software_challenge_client/field.rb @@ -17,9 +17,9 @@ class Field # @!attribute [r] y # @return [Integer] the field's y-coordinate attr_reader :y - + # Initializer - # + # # @param type [FieldType] field type # @param x [Integer] x-coordinate # @param y [Integer] y-coordinate @@ -29,14 +29,14 @@ def initialize(type, x, y) @x = x @y = y end - + def ==(another_field) - return self.ownerColor == another_field.ownerColor && - self.type == another_field.type && - self.x == another_field.x && + return self.ownerColor == another_field.ownerColor && + self.type == another_field.type && + self.x == another_field.x && self.y == another_field.y end - + def to_s return "Field: x = #{self.x}, y = #{self.y}, owner = #{self.ownerColor}, type = #{self.type}" end diff --git a/lib/software_challenge_client/game_state.rb b/lib/software_challenge_client/game_state.rb index b94b0ce..12f6b33 100644 --- a/lib/software_challenge_client/game_state.rb +++ b/lib/software_challenge_client/game_state.rb @@ -10,7 +10,7 @@ # @author Ralf-Tobias Diekert # The state of a game class GameState - + # @!attribute [rw] turn # @return [Integer] turn number attr_accessor :turn @@ -35,18 +35,18 @@ class GameState # @!attribute [rw] condition # @return [Condition] the winner and winning reason attr_accessor :condition - + def initialize self.currentPlayerColor = PlayerColor::RED self.startPlayerColor = PlayerColor::RED self.board = Board.new(true) end - + # adds a player to the gamestate # # @param player [Player] the player, that will be added - def addPlayer(player) - if player.color == PlayerColor::RED + def addPlayer(player) + if player.color == PlayerColor::RED @red = player else if player.color == PlayerColor::BLUE @blue = player @@ -66,34 +66,34 @@ def currentPlayer end # gets the other (not the current) player - # + # # @return [Player] the other (not the current) player def otherPlayer if self.currentPlayerColor == PlayerColor::RED - return self.blue + return self.blue else return self.red end end - + # gets the other (not the current) player's color # # @return [PlayerColor] the other (not the current) player's color def otherPlayerColor return PlayerColor.opponentColor(self.currentPlayerColor) end - + # gets the start player # # @return [Player] the startPlayer def startPlayer - if self.startPlayer == PlayerColor::RED + if self.startPlayer == PlayerColor::RED return self.red else return self.blue end end - + # switches current player def switchCurrentPlayer if currentPlayer.color == PlayerColor::RED @@ -102,7 +102,7 @@ def switchCurrentPlayer @currentPlayer = self.red end end - + # prepares next turn and sets the last move # # @param [Move] the last move @@ -111,14 +111,14 @@ def prepareNextTurn(lastMove) @lastMove = lastMove; self.switchCurrentPlayer() end - + # gets the current round # # @return [Integer] the current round def round return self.turn / 2 end - + # gets all possible moves # # @return [Array] a list of all possible moves @@ -136,18 +136,18 @@ def getPossibleMoves end return moves end - + # performs a move on the gamestate # # @param move [Move] the move, that will be performed # @param player [Player] the player, who makes the move def perform(move, player) if !move.nil? - if move.x < Constants::SIZE && move.y < Constants::SIZE && + if move.x < Constants::SIZE && move.y < Constants::SIZE && move.x >= 0 && move.y >= 0 - if self.getPossibleMoves.include?(move) + if self.getPossibleMoves.include?(move) self.board.put(move.x, move.y, player) - player.points = self.pointsForPlayer(player) + player.points = self.pointsForPlayer(player) else raise "Der Zug ist nicht möglich, denn der Platz ist bereits besetzt oder nicht besetzbar." end @@ -156,7 +156,7 @@ def perform(move, player) end end end - + # gets a player's points # # @param player [Player] the player, whos statistics will be returned @@ -164,19 +164,19 @@ def perform(move, player) def playerStats(player) return self.playerStats(player.color) end - + # gets a player's points by the player's color # # @param playerColor [PlayerColor] the player's color, whos statistics will be returned # @return [Integer] the points of the player - def playerStats(playerColor) + def playerStats(playerColor) if playerColor == PlayerColor::RED return self.gameStats[0]; - else + else return self.gameStats[1] end end - + # gets the players' statistics # # @return [Array] the points for both players @@ -185,17 +185,17 @@ def gameStats stats[0][0] = self.red.points stats[1][0] = self.blue.points - + return stats end - + # get the players' names # # @return [Array] the names for both players def playerNames return [red.displayName, blue.displayName] end - + # sets the game-ended condition # # @param winner [Player] the winner of the game @@ -205,28 +205,28 @@ def endGame(winner, reason) @condition = Condition.new(winner, reason) end end - + # has the game ended? # # @return [Boolean] true, if the game has allready ended def gameEnded? return !self.condition.nil? end - + # gets the game's winner # # @return [Player] the game's winner def winner return condition.nil? ? nil : self.condition.winner end - + # gets the winning reason # # @return [String] the winning reason def winningReason return condition.nil? ? nil : self.condition.reason end - + # calculates a player's points # # @param player [Player] the player, whos point will be calculated @@ -271,7 +271,7 @@ def pointsForPlayer(player) longestPath = fields[1].x - fields[0].x end end - + return longestPath # return longestPath end @@ -336,9 +336,9 @@ def circuit(circuit, visited) circuit.push(*toBeAddedFields) if changed return self.circuit(circuit, visited) - else + else return circuit end end - + end \ No newline at end of file diff --git a/lib/software_challenge_client/move.rb b/lib/software_challenge_client/move.rb index 5ab178b..d50f256 100644 --- a/lib/software_challenge_client/move.rb +++ b/lib/software_challenge_client/move.rb @@ -13,9 +13,9 @@ class Move # @!attribute [r] hints # @return [Array] the move's hints attr_reader :hints - + # Initializer - # + # # @param x [Integer] x-coordinate # @param y [Integer] y-coordinate def initialize(x, y) @@ -23,7 +23,7 @@ def initialize(x, y) @y = y @hints = Array.new end - + # @overload addHint(hint) # adds a hint to the move # @param hint [DebugHint] the added hint @@ -37,17 +37,17 @@ def initialize(x, y) def addHint(hint) @hints.push(hint); end - + # adds a hint to the move def addHint(key, value) self.addHint(DebugHint.new(key, value)) end - + # adds a hint to the move def addHint(string) self.addHint(DebugHint.new(string)) end - + def ==(another_move) return self.x == another_move.x && self.y == another_move.y end diff --git a/lib/software_challenge_client/network.rb b/lib/software_challenge_client/network.rb index d349453..9752784 100644 --- a/lib/software_challenge_client/network.rb +++ b/lib/software_challenge_client/network.rb @@ -12,36 +12,36 @@ class Network @socket @host @port - + @board @client @protocol - + @receiveBuffer @reservationID - + # @!attribute [r] connected # @return [Boolean] true, if the client is connected to a server attr_reader :connected - + def initialize(host, port, board, client) - @host, @port, @connected, @board, @client = + @host, @port, @connected, @board, @client = host, port, false, board, client - + @protocol = Protocol.new(self, @client) @reservationID = '' @receiveBuffer = '' - + puts '> Network/Socket created.' end # connects the client with a given server - # + # # @return [Boolean] true, if successfully connected to the server def connect @socket = TCPSocket.open(@host, @port) @connected = true - + self.sendString('') if @reservationID != '' document = REXML::Docuent.new @@ -49,7 +49,7 @@ def connect element.add_attribute('reservationCode', @reservationID) document.add(element) self.sendXML(document) - else + else document = REXML::Document.new element = REXML::Element.new('join') element.add_attribute('gameType', 'swc_2016_twixt') @@ -58,7 +58,7 @@ def connect end return @connected end - + # disconnects the client from a server def disconnect @@ -74,10 +74,10 @@ def disconnect def readString puts 'reading' sockMsg = '' - if(!@connected) + if(!@connected) return end - + line ='' char = '' while line!="" @@ -91,7 +91,7 @@ def readString end puts 'ended reading' if sockMsg != '' - + @receiveBuffer.concat(sockMsg) # Remove tag @@ -100,7 +100,7 @@ def readString puts 'Receive:' puts '' #puts @receiveBuffer - + # Process text @protocol.processString(''+@receiveBuffer+''); self.emptyReceiveBuffer diff --git a/lib/software_challenge_client/player.rb b/lib/software_challenge_client/player.rb index 6c1f8f9..80c308e 100644 --- a/lib/software_challenge_client/player.rb +++ b/lib/software_challenge_client/player.rb @@ -10,16 +10,16 @@ class Player # @!attribute [rw] points # @return [Integer] the player's points attr_accessor :points - + # Initializer # @param the new player's color def initialize(color) @color = color self.points = 0 end - + def ==(another_player) return self.color == another_player.color end - + end \ No newline at end of file diff --git a/lib/software_challenge_client/player_color.rb b/lib/software_challenge_client/player_color.rb index ec83b06..47e93ba 100644 --- a/lib/software_challenge_client/player_color.rb +++ b/lib/software_challenge_client/player_color.rb @@ -5,7 +5,7 @@ module PlayerColor NONE = 1 RED = 2 BLUE = 4 - + # Returns the opponents Color # # @param color [PlayerColor] The player's color, whose opponent needs to be found diff --git a/lib/software_challenge_client/protocol.rb b/lib/software_challenge_client/protocol.rb index 3857026..63a6566 100644 --- a/lib/software_challenge_client/protocol.rb +++ b/lib/software_challenge_client/protocol.rb @@ -13,7 +13,7 @@ # This class handles the parsing of xml strings according to the network protocol of twixt class Protocol include REXML::StreamListener - + # @!attribute [r] gamestate # @return [Gamestate] current gamestate attr_reader :gamestate @@ -27,19 +27,19 @@ class Protocol def initialize(network, client) @gamestate = GameState.new - @network, @client = network, client + @network, @client = network, client self.client.gamestate = self.gamestate end - + # starts xml-string parsing - # + # # @param text [String] the xml-string that will be parsed def processString(text) list = self #puts "Parse XML:\n#{text}\n----END XML" REXML::Document.parse_stream(text, list) end - + # called if an end-tag is read # # @param name [String] the end-tag name, that was read @@ -94,7 +94,7 @@ def tag_start(name, attrs) @gamestate.startPlayerColor = attrs['startPlayer'] == 'RED' ? PlayerColor::RED : PlayerColor::BLUE @gamestate.currentPlayerColor = attrs['currentPlayer'] == 'RED' ? PlayerColor::RED : PlayerColor::BLUE puts "Turn: #{@gamestate.turn}" - when "red" + when "red" puts 'new red player' @gamestate.addPlayer(Player.new(attrs['color'] == 'RED' ? PlayerColor::RED : PlayerColor::BLUE)) @gamestate.red.points = attrs['points'].to_i @@ -144,7 +144,7 @@ def tag_start(name, attrs) # # @param document [REXML::Document] the document, that will be send to the connected server def sendXml(document) - @network.sendXML(document) + @network.sendXML(document) end - + end diff --git a/lib/software_challenge_client/version.rb b/lib/software_challenge_client/version.rb index 7bed3fe..8443fe6 100644 --- a/lib/software_challenge_client/version.rb +++ b/lib/software_challenge_client/version.rb @@ -1,4 +1,4 @@ # encoding: UTF-8 module SoftwareChallengeClient - VERSION = "0.1.1" + VERSION = "0.1.2" end