Commits

Tomoya Chiba committed 584cce6

tcp server

  • Participants
  • Parent commits 48f1e94

Comments (0)

Files changed (7)

File client/reversi-client.coffee

 
 ReversiRule =
-  white : -1
   black : 1
+  white : -1
 
 # updateStones = {posPoint: Stone, revpoints: [Stone]}
 

File controllers/reversi-server.coffee

     @state = 'waiting'
     @board = null
     @players = []
+    @options = {}
+    @illigalPlayer = null
+    @illigalReason = null
     @colors = [ReversiBoard.black, ReversiBoard.white]
 
-  _addUser: (username) ->
+  _addUser: (username, options) ->
     console.log "players: #{@players} (length: #{@players.length})"
     if @players.length < 2
       if @players.indexOf(username) < 0
         @players.push username
+        @options[username] = options
         return true
     false
 
     console.log "players: #{@players} (length: #{@players.length})"
     if (idx = @players.indexOf(username)) >= 0
       @players.splice(idx, 1)
+      delete @options[username]
       console.log "removed:: players: #{@players} (length: #{@players.length})"
-      return true
-    false
+      true
+    else
+      false
 
   turnPlayer: () ->
     return null unless @state == 'game'
   isGameEnd: ->
     @board.isGameEnd()
 
+  illigalMoveGameEnd: (username)->
+    @illigalPlayer = username
+    @board.gameEnd()
+
   gameResult: ->
     self = @
 
     userColor = @getColor(username)
     stone = @board.countStone()
 
-    wl = new Array(2)
-    if stone.white > stone.black
-      wl = ['Win', 'Lose']
-    else if stone.white < stone.black
-      wl = ['Lose', 'Win']
+    issue = null
+    reason = null
+    if @illigalPlayer
+      issue = if @illigalPlayer == username then 'LOSE' else 'WIN'
+      reason = @illigalReason
     else
-      wl = ['Tie', 'Tie']
+      wl = new Array(2)
+      if stone.white > stone.black
+        wl = ['WIN', 'LOSE']
+      else if stone.white < stone.black
+        wl = ['LOSE', 'WIN']
+      else
+        wl = ['TIE', 'TIE']
+
+      idx = [ReversiBoard.white, ReversiBoard.black].indexOf(userColor)
+      issue = wl[idx]
+      reason = "DOUBLE_PASS"
 
-    idx = [ReversiBoard.white, ReversiBoard.black].indexOf(userColor)
-      
     result =
       color: userColor
-      issue: wl[idx]
+      issue: issue 
+      reason: reason
       black: stone.black
       white: stone.white
   
 
   startGame: () ->
     return false unless @state == 'waiting' && @players.length == 2
+    @illigalPlayer = null
     @state = 'game'
-    @board = new ReversiBoard()
     if Math.random() > 0.5
       tmp = @colors[0]
       @colors[0] = @colors[1]
       @colors[1] = tmp
+
+    blackplayer = @findUserByColor(ReversiBoard.black)
+    whiteplayer = @findUserByColor(ReversiBoard.white)
+
+    ap = @options[blackplayer].autoPass || @options[whiteplayer].autoPass
+    autoPassFlag = 
+      black: ap
+      white: ap
+
+    @board = new ReversiBoard(autoPassFlag)
+
     true
 
   cancelGame: () ->
   move: (username, x, y) ->
     return null unless @state == 'game'
     console.log "move x: #{x}, y: #{y}, color: #{@getColor(username)}"
-    update = @board.put(x, y, @getColor(username))
+    result = @board.put(x, y, @getColor(username))
+
+    update = if result then result.update else null
+    autoPass = if result then result.autoPass else 0
+    success = update != null
+    if !success && @options[username].illigalMoveLose
+      @illigalMoveGameEnd(username,"ILLEGAL_MOVE")
 
     result =
-      success: update != null
+      success: success 
       update: update
+      autoPass: autoPass
+      gameEnd: @isGameEnd()
+      nextTurnPlayer: @turnPlayer()
+      nextColor: @board.turn
+
+  pass: (username) ->
+    return {success: false} unless @turnPlayer() == username
+    result = @board.pass()
+
+    if !result.success && @options[username].illigalMoveLose
+      @illigalMoveGameEnd(username, "ILLEGAL_MOVE")
+
+    result =
+      success: result.success
+      autoPass: result.autoPass
       gameEnd: @isGameEnd()
       nextTurnPlayer: @turnPlayer()
       nextColor: @board.turn
 
+
   _gameStartInfo: ->
     players: @players
     nextTurnPlayer: @turnPlayer()
     nextColor: @board.turn
 
-  @login: (room, username, callback) ->
+  @login: (room, username, options, callback) ->
     if !room then room = new ReversiRoom
-    success = room._addUser(username)
+    success = room._addUser(username, options)
     isGameStart = room.startGame()
     status =
       success: success 
     return @fail(username, 'login failed') if info && info.state.type == 'login'
     maskedName = @maskName(username)
 
-    ReversiRoom.login @_roomList[roomname], username, (room, status) ->
+    ReversiRoom.login @_roomList[roomname], username, info.options, (room, status) ->
       console.log status
       self._roomList[roomname] = room
 
       when 'login'
         roomname = info.state.roomname
         room = @_roomList[roomname]
-
-        result = room.move(username, x, y)
-
-        if result.success
-          @requestNoticeToGroup roomname, 'game update',
-            update: result.update
-            username: username
-            isLastTurn: result.gameEnd
-
-            if result.gameEnd
-              @noticeGameEnd(roomname)
-            else
-              @requestNotice result.nextTurnPlayer, 'game turn',
-                color: result.nextColor
-        else if info.options.loseIlligalMove
-          console.log "lose"
-          # lose
+        
+        result = if x && y then room.move(username, x, y) else room.pass(username)
+        console.log result
+        console.log arguments
 
         @moveResponseNotice(username, result.success)
+        if result.success
+          if result.update
+            @requestNoticeToGroup roomname, 'game update',
+              update: result.update
+              username: username
+              isLastTurn: result.gameEnd
+          else
+            @requestNoticeToGroup roomname, 'game pass',
+              username: username
+              isLastTurn: result.gameEnd
+
+          if result.autoPass > 0
+            @requestNoticeToGroup roomname, 'game autopass',
+              username: username 
+              isLastTurn: result.gameEnd
+
+          if result.gameEnd
+            @noticeGameEnd(roomname)
+          else
+            @requestNotice result.nextTurnPlayer, 'game turn',
+              color: result.nextColor
       else
         @moveResponseNotice(username, false)
-
+ 
   pass: (username) ->
-    @moveResponseNotice(username, true)
+    @move(username, null, null)
 
   moveResponseNotice: (username, success) ->
     @requestNotice username, 'move submitted',

File controllers/reversi.coffee

     else
       false
 
-  constructor: (first) ->
+  constructor: (@autoPassFlags) ->
+    @autoPassFlags = @autoPassFlags || {black: true, white: true}
+    @passCount = 0
     @board = (new Array(10) for _v in new Array(10))
     for val, i in @board
       for _v, j in val
     @board[4][5] = Reversi.black
     @board[5][4] = Reversi.black
 
-    @turn = first || Reversi.black
+    @turn = Reversi.black
     @updateStack = null
 
   colorXY: (x, y) -> @board[x][y]
   
   put: (x, y, color) ->
     return null unless @turn == color && @canPut(x, y, color)
+    @passCount = 0
 
     @updateStack = new UpdateStack(point(x, y), color, @updateStack)
     @board[x][y] = color
 
     count = 0
 
-    until @canPutCheck() || count++ > 1
-      @turn = - @turn
-    @turn = Reversi.gameEnd if count > 2
+    autoPassCount = @autoPass()
+    { update: @updateStack.newest(), autoPass: autoPassCount }
+
+  pass: ->
+    unless @canPutCheck()
+      if @passCount++ > 0
+        @turn = Reversi.gameEnd
+        {success: true, autoPass: 0}
+      else
+        @turn = - @turn
+        autoPassCount = @autoPass()
+        {success: true, autoPass: autoPassCount}
+    else
+      {success: false, autoPass: 0}
+  
+  autoPass: ->
+    colorKey = if @turn == Reversi.black then 'black' else 'white'
+    if @autoPassFlags[colorKey]
+      unless @turn == Reversi.gameEnd
+        result = @pass()
+        return if result.success then result.autoPass + 1 else result.autoPass
+    return 0
 
-    @updateStack.newest()
-    
   canPut: (x, y, color) ->
     return false unless @colorXY(x, y) == 0
     vector = surrounds(0, 0)
     false
 
   isGameEnd: -> @turn == Reversi.gameEnd
+  gameEnd: -> @turn = Reversi.gameEnd
+
   countStone: ->
     blackStones = 0
     whiteStones = 0

File controllers/socketio-connector.coffee

 
     @operator.register username, socket, self,
       maskName: true
+      autoPass: true
 
     # self._userStates[socket.id] = state: 'waiting'
 

File controllers/tcp-server.coffee

     socket.on 'close', ->
       console.log "server-> close connection #{socket.remoteAddress}:#{socket.remotePort}"
       self.operator.disconnect client.username if client.username
-
+    
+    socket.on 'error', ->
+      console.log "error occured"
+      # console.log arguments
+      self.operator.disconnect client.username if client.username
+      self.end
 
   doCommand: (com, client) ->
     switch com.command
       when 'OPEN'
-        username = com.args[0]
 
-        nameSplit = username.split(",") 
+        nameSplit = com.args[0].split(":") 
         console.log nameSplit
-        roomname = if nameSplit.length > 1 then roomname = nameSplit[0] else username
+        roomname = if nameSplit.length > 1 then nameSplit[0] else nameSplit[0]
+        username = if nameSplit.length > 1 then nameSplit[1] else nameSplit[0]
 
         client.username = username
         @clients[username] = client
         @operator.register username, client, this,
-          loseIlligalMove: true
+          illigalMoveLose: true
+          autoPass: false
         @operator.login username, roomname 
 
       when 'MOVE'
         unless username == data.username || data.isLastTurn
           ptstr = TcpConnector.convertPos(data.update.point.x, data.update.point.y)
           client.socket.write "MOVE #{ptstr}\n"
+      when 'game pass'
+        unless username == data.username || data.isLastTurn
+          client.socket.write "MOVE PASS\n"
+      when 'game autopass'
+        if username == data.username && !data.isLastTurn
+          client.socket.write "MOVE PASS\n"
       when 'move submitted'
         if data.success
           client.socket.write "ACK 60000\n"
       when 'game end'
         if data.color == Reversi.black
-          client.socket.write "END #{data.issue} #{data.black} #{data.white} DOUBLE_PASS\n"
+          client.socket.write "END #{data.issue} #{data.black} #{data.white} #{data.reason}\n"
         else
-          client.socket.write "END #{data.issue} #{data.white} #{data.black} DOUBLE_PASS\n"
+          client.socket.write "END #{data.issue} #{data.white} #{data.black} #{data.reason}\n"
         client.socket.write "BYE\n"
         
   @parser: (buffer, str) ->

File test/controllers/reversi-server-test.coffee

             switch client.id
               when testClients[turnPlayer[0]].id
                 data.color.should.eql Reversi.black
-                data.issue.should.eql 'Win'
+                data.issue.should.eql 'WIN'
               when testClients[turnPlayer[1]].id
                 data.color.should.eql Reversi.white
-                data.issue.should.eql 'Lose'
+                data.issue.should.eql 'LOSE'
             data.black.should.eql(5)
             data.white.should.eql(0)
             check()
 
-      revServer.register(usernames[0], testClients[0], testConnector)
-      revServer.register(usernames[1], testClients[1], testConnector)
+      revServer.register(usernames[0], testClients[0], testConnector, autoPass: true)
+      revServer.register(usernames[1], testClients[1], testConnector, autoPass: true)
       revServer.login(usernames[0], roomname)
       revServer.login(usernames[1], roomname)
 

File test/controllers/reversi-test.coffee

       rev = new ReversiBoard()
 
     it 'put (3, 4, black)', ->
-      update = rev.put(3, 4, ReversiBoard.black)
+      update = rev.put(3, 4, ReversiBoard.black).update
       assert.equal 3, update.point.x
       assert.equal 4, update.point.y
       assert.equal ReversiBoard.black, update.color
       assert.equal 4, update.revPoints[0].y
 
     it 'put (3, 4, white)', ->
-      update = rev.put(3, 4, ReversiBoard.white)
-      assert.equal null, update
+      result = rev.put(3, 4, ReversiBoard.white)
+      assert.equal null, result
 
   describe 'countStone', ->
     rev = null
       assert.equal 0, stone.white
 
       assert.equal true, rev.isGameEnd()
+    it 'pass', ->
+      rev = new ReversiBoard
+        black: false
+        white: false
+
+      rev.board[4][4] = ReversiBoard.black
+      rev.board[5][5] = ReversiBoard.black
+
+      res1 = rev.pass()
+      res2 = rev.pass()
+
+      stone = rev.countStone()
+
+      assert.equal 0, res1.autoPass
+      assert.equal 0, res2.autoPass
+
+      assert.equal 4, stone.black
+      assert.equal 0, stone.white
+
+      assert.equal true, rev.isGameEnd()
+    it 'auto pass', ->
+      rev = new ReversiBoard
+        black: false
+        white: true
+
+      rev.board[4][4] = ReversiBoard.black
+      rev.board[5][5] = ReversiBoard.black
+
+      res = rev.pass()
+
+      console.log res
+      assert.equal 1, res.autoPass
+
+      stone = rev.countStone()
+      assert.equal 4, stone.black
+      assert.equal 0, stone.white
+
+      assert.equal true, rev.isGameEnd()