software_challenge_client 22.0.3 → 22.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/RELEASES.md +8 -0
- data/lib/software_challenge_client/game_state.rb +158 -157
- data/lib/software_challenge_client/protocol.rb +201 -202
- data/lib/software_challenge_client/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 910f87c3bca7d1aa880039a0c4bd5953965f3ddd2ebd48aff96b0f14c2010331
|
4
|
+
data.tar.gz: cf0d306bc178528d2e38156dc1654efc5e67f6f877aaf542ff0fb9b80e51705a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6341fba9ff7f9dde85015a7493a5187d9fcdfea97fe912159e4dd2cdd82283109338b5788dabd25698474de9b7fad27d6b66480e3c7a34047c159bc5e5900969
|
7
|
+
data.tar.gz: 6ff8469aa8d35ddc861dc771d8124ed243697c1db2b3996bd17864f405c0fe91d8a348200b20b9cb359574e71cd1168b925958615d1c23dd025cb0941006dc8d
|
data/RELEASES.md
CHANGED
@@ -1,157 +1,158 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative './util/constants'
|
4
|
-
require_relative 'player'
|
5
|
-
require_relative 'board'
|
6
|
-
require_relative 'condition'
|
7
|
-
require_relative 'color'
|
8
|
-
|
9
|
-
# Ein Spielzustand. Wird vom Server an die Computerspieler übermittelt und
|
10
|
-
# enthält alles, was der Computerspieler wissen muss, um einen Zug zu machen.
|
11
|
-
#
|
12
|
-
# Um eine Liste der gerade möglichen Züge zu bekommen, gibt es die Methode
|
13
|
-
# {GameState#possible_moves}.
|
14
|
-
class GameState
|
15
|
-
# @!attribute [rw] turn
|
16
|
-
# @return [Integer] Aktuelle Zugnummer (von 0 beginnend)
|
17
|
-
attr_accessor :turn
|
18
|
-
|
19
|
-
# @!attribute [
|
20
|
-
# @return [
|
21
|
-
|
22
|
-
|
23
|
-
# @!attribute [r]
|
24
|
-
# @return [Player] Der
|
25
|
-
attr_reader :
|
26
|
-
|
27
|
-
# @!attribute [
|
28
|
-
# @return [
|
29
|
-
|
30
|
-
|
31
|
-
# @!attribute [rw]
|
32
|
-
# @return [
|
33
|
-
attr_accessor :
|
34
|
-
|
35
|
-
# @!attribute [rw]
|
36
|
-
# @return [
|
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
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './util/constants'
|
4
|
+
require_relative 'player'
|
5
|
+
require_relative 'board'
|
6
|
+
require_relative 'condition'
|
7
|
+
require_relative 'color'
|
8
|
+
|
9
|
+
# Ein Spielzustand. Wird vom Server an die Computerspieler übermittelt und
|
10
|
+
# enthält alles, was der Computerspieler wissen muss, um einen Zug zu machen.
|
11
|
+
#
|
12
|
+
# Um eine Liste der gerade möglichen Züge zu bekommen, gibt es die Methode
|
13
|
+
# {GameState#possible_moves}.
|
14
|
+
class GameState
|
15
|
+
# @!attribute [rw] turn
|
16
|
+
# @return [Integer] Aktuelle Zugnummer (von 0 beginnend)
|
17
|
+
attr_accessor :turn
|
18
|
+
|
19
|
+
# @!attribute [r] player_one
|
20
|
+
# @return [Player] Der erste Spieler
|
21
|
+
attr_reader :player_one
|
22
|
+
|
23
|
+
# @!attribute [r] player_two
|
24
|
+
# @return [Player] Der zweite Spieler
|
25
|
+
attr_reader :player_two
|
26
|
+
|
27
|
+
# @!attribute [rw] start_team
|
28
|
+
# @return [Team] Der Spieler der zuerst zieht
|
29
|
+
attr_accessor :start_team
|
30
|
+
|
31
|
+
# @!attribute [rw] board
|
32
|
+
# @return [Board] Das aktuelle Spielbrett
|
33
|
+
attr_accessor :board
|
34
|
+
|
35
|
+
# @!attribute [rw] last_move
|
36
|
+
# @return [Move] Der zuletzt gemachte Zug (ist nil vor dem ersten Zug, also
|
37
|
+
# bei turn == 0)
|
38
|
+
attr_accessor :last_move
|
39
|
+
|
40
|
+
# @!attribute [rw] condition
|
41
|
+
# @return [Condition] Gewinner und Gewinngrund, falls das Spiel bereits
|
42
|
+
# entschieden ist, sonst nil.
|
43
|
+
attr_accessor :condition
|
44
|
+
|
45
|
+
# Zugriff auf ein Feld des Spielbrettes. Siehe {Board#field}.
|
46
|
+
def field(x, y)
|
47
|
+
board.field(x, y)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Erstellt einen neuen leeren Spielstand.
|
51
|
+
def initialize
|
52
|
+
@board = Board.new
|
53
|
+
@turn = 0
|
54
|
+
end
|
55
|
+
|
56
|
+
# Fügt einen Spieler zum Spielzustand hinzu.
|
57
|
+
#
|
58
|
+
# @param player [Player] Der hinzuzufügende Spieler.
|
59
|
+
def add_player(player)
|
60
|
+
case player.color
|
61
|
+
when Color::RED
|
62
|
+
@player_one = player
|
63
|
+
when Color::BLUE
|
64
|
+
@player_two = player
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# @return [Player] Spieler, der gerade an der Reihe ist.
|
69
|
+
def current_player
|
70
|
+
turn.even? ? player_one : player_two
|
71
|
+
end
|
72
|
+
|
73
|
+
# @return [Player] Spieler, der gerade nicht an der Reihe ist.
|
74
|
+
def other_player
|
75
|
+
turn.even? ? player_two : player_one
|
76
|
+
end
|
77
|
+
|
78
|
+
# @return [Team] Typ des Spielers, der gerade nicht an der Reihe ist.
|
79
|
+
def other_team
|
80
|
+
other_player.type
|
81
|
+
end
|
82
|
+
|
83
|
+
# @return [Integer] Aktuelle Rundennummer (von 1 beginnend)
|
84
|
+
def round
|
85
|
+
turn / 2 + 1
|
86
|
+
end
|
87
|
+
|
88
|
+
# @return [Bool] Ob diese gamestate in der ersten Runde ist
|
89
|
+
def is_first_move?
|
90
|
+
round == 1
|
91
|
+
end
|
92
|
+
|
93
|
+
# Führt einen Zug auf dem Spielzustand aus. Das Spielbrett wird entsprechend
|
94
|
+
# modifiziert.
|
95
|
+
#
|
96
|
+
# @param move [Move] Der auszuführende Zug.
|
97
|
+
def perform!(move)
|
98
|
+
GameRuleLogic.perform_move(self, move)
|
99
|
+
end
|
100
|
+
|
101
|
+
# @return [Boolean] true, falls das Spiel bereits geendet hat, false bei noch
|
102
|
+
# laufenden Spielen.
|
103
|
+
def game_ended?
|
104
|
+
!condition.nil?
|
105
|
+
end
|
106
|
+
|
107
|
+
# @return [Player] Der Spieler, der das Spiel gewonnen hat, falls dies schon
|
108
|
+
# entschieden ist. Sonst false.
|
109
|
+
def winner
|
110
|
+
condition.nil? ? nil : condition.winner
|
111
|
+
end
|
112
|
+
|
113
|
+
# @return [String] Der Grund, warum das Spiel beendet wurde, nil falls das
|
114
|
+
# Spiel noch läuft.
|
115
|
+
def winning_reason
|
116
|
+
condition.nil? ? nil : condition.reason
|
117
|
+
end
|
118
|
+
|
119
|
+
# Ermittelt die Punkte eines Spielers. Wenn das Spiel durch Erreichen des
|
120
|
+
# Rundenlimits beendet wird, hat der Spieler mit den meisten Punkten gewonnen.
|
121
|
+
#
|
122
|
+
# @param player [Player] Der Spieler, dessen Punkte berechnet werden sollen.
|
123
|
+
# @return [Integer] Die Punkte des Spielers
|
124
|
+
def points_for_player(_player)
|
125
|
+
# TODO
|
126
|
+
-1
|
127
|
+
end
|
128
|
+
|
129
|
+
def ==(other)
|
130
|
+
turn == other.turn &&
|
131
|
+
start_color == other.start_color &&
|
132
|
+
current_color == other.current_color &&
|
133
|
+
blue == other.blue &&
|
134
|
+
yellow == other.yellow &&
|
135
|
+
red == other.red &&
|
136
|
+
green == other.green &&
|
137
|
+
board == other.board &&
|
138
|
+
lastMove == other.lastMove &&
|
139
|
+
condition == other.condition
|
140
|
+
end
|
141
|
+
|
142
|
+
# Erzeugt eine Kopie des Spielzustandes. Änderungen an dieser Kopie
|
143
|
+
# beeinflussen den originalen Spielzustand nicht. Die Kopie kann also zum
|
144
|
+
# testen von Spielzügen genutzt werden.
|
145
|
+
def clone
|
146
|
+
Marshal.load(Marshal.dump(self))
|
147
|
+
end
|
148
|
+
|
149
|
+
# Wechselt den Spieler, der aktuell an der Reihe ist.
|
150
|
+
def switch_current_player
|
151
|
+
@current_player_color = other_player_color
|
152
|
+
end
|
153
|
+
|
154
|
+
# @return [Array<Field>] Alle Felder mit Blöcken des Spielers, der gerade an der Reihe ist.
|
155
|
+
def own_fields
|
156
|
+
board.fields_of_color(current_player.color)
|
157
|
+
end
|
158
|
+
end
|
@@ -1,202 +1,201 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
# frozen_string_literal: true
|
3
|
-
require 'socket'
|
4
|
-
require_relative 'board'
|
5
|
-
require_relative 'move'
|
6
|
-
require_relative 'piece_type'
|
7
|
-
require_relative 'player'
|
8
|
-
require_relative 'network'
|
9
|
-
require_relative 'client_interface'
|
10
|
-
require 'rexml/document'
|
11
|
-
require 'rexml/streamlistener'
|
12
|
-
require 'builder'
|
13
|
-
|
14
|
-
# This class handles communication to the server over the XML communication
|
15
|
-
# protocol. Messages from the server are parsed and moves are serialized and
|
16
|
-
# send back.
|
17
|
-
class Protocol
|
18
|
-
include Logging
|
19
|
-
include REXML::StreamListener
|
20
|
-
|
21
|
-
# @!attribute [r] gamestate
|
22
|
-
# @return [Gamestate] current gamestate
|
23
|
-
attr_reader :gamestate
|
24
|
-
# @!attribute [rw] roomId
|
25
|
-
# @return [String] current room id
|
26
|
-
attr_accessor :roomId
|
27
|
-
# @!attribute [r] client
|
28
|
-
# @return [ClientInterface] current client
|
29
|
-
attr_reader :client
|
30
|
-
|
31
|
-
def initialize(network, client)
|
32
|
-
@gamestate = GameState.new
|
33
|
-
@network = network
|
34
|
-
@client = client
|
35
|
-
@context = {} # for saving context when stream-parsing the XML
|
36
|
-
@client.gamestate = @gamestate
|
37
|
-
end
|
38
|
-
|
39
|
-
# starts xml-string parsing
|
40
|
-
#
|
41
|
-
# @param text [String] the xml-string that will be parsed
|
42
|
-
def process_string(text)
|
43
|
-
#logger.debug "Parse XML:\n#{text}\n----END XML"
|
44
|
-
begin
|
45
|
-
REXML::Document.parse_stream(text, self)
|
46
|
-
rescue REXML::ParseException => e
|
47
|
-
# to parse incomplete xml, ignore missing end tag exceptions
|
48
|
-
raise e unless e.message =~ /Missing end tag/
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
# called when text is encountered
|
53
|
-
def text(text)
|
54
|
-
@context[:last_text] = text
|
55
|
-
end
|
56
|
-
|
57
|
-
# called if an end-tag is read
|
58
|
-
#
|
59
|
-
# @param name [String] the end-tag name, that was read
|
60
|
-
def tag_end(name)
|
61
|
-
case name
|
62
|
-
when 'board'
|
63
|
-
logger.debug @gamestate.board.to_s
|
64
|
-
when 'startTeam'
|
65
|
-
@gamestate.add_player(Player.new(Color::RED, "ONE", 0))
|
66
|
-
@gamestate.add_player(Player.new(Color::BLUE, "TWO", 0))
|
67
|
-
if @context[:last_text] == "ONE"
|
68
|
-
@gamestate.start_team = @gamestate.player_one
|
69
|
-
else
|
70
|
-
@gamestate.start_team = @gamestate.player_two
|
71
|
-
end
|
72
|
-
when 'team'
|
73
|
-
@context[:team] = @context[:last_text]
|
74
|
-
when 'int'
|
75
|
-
if @context[:team] == "ONE"
|
76
|
-
logger.info 'Got player one amber'
|
77
|
-
@gamestate.player_one.amber = @context[:last_text].to_i
|
78
|
-
else
|
79
|
-
logger.info 'Got player two amber'
|
80
|
-
@gamestate.player_two.amber = @context[:last_text].to_i
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
# called if a start tag is read
|
86
|
-
# Depending on the tag the gamestate is updated
|
87
|
-
# or the client will be asked for a move
|
88
|
-
#
|
89
|
-
# @param name [String] the start-tag, that was read
|
90
|
-
# @param attrs [Dictionary<String, String>] Attributes attached to the tag
|
91
|
-
def tag_start(name, attrs)
|
92
|
-
case name
|
93
|
-
when 'room'
|
94
|
-
@roomId = attrs['roomId']
|
95
|
-
logger.info 'roomId : ' + @roomId
|
96
|
-
when 'data'
|
97
|
-
logger.debug "data(class) : #{attrs['class']}"
|
98
|
-
@context[:data_class] = attrs['class']
|
99
|
-
if attrs['class'] == 'moveRequest'
|
100
|
-
@client.gamestate = gamestate
|
101
|
-
move = @client.move_requested
|
102
|
-
sendString(move_to_xml(move))
|
103
|
-
end
|
104
|
-
if attrs['class'] == 'error'
|
105
|
-
logger.info "Game ended - ERROR: #{attrs['message']}"
|
106
|
-
@network.disconnect
|
107
|
-
end
|
108
|
-
if attrs['class'] == 'result'
|
109
|
-
logger.info 'Got game result'
|
110
|
-
@network.disconnect
|
111
|
-
@gamestate.condition = Condition.new(nil, '')
|
112
|
-
end
|
113
|
-
when 'state'
|
114
|
-
logger.debug 'new gamestate'
|
115
|
-
@gamestate = GameState.new
|
116
|
-
@gamestate.turn = attrs['turn'].to_i
|
117
|
-
@gamestate.round
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
@context[:
|
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
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
#
|
181
|
-
#
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
#
|
191
|
-
#
|
192
|
-
#
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
d.
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
end
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require 'socket'
|
4
|
+
require_relative 'board'
|
5
|
+
require_relative 'move'
|
6
|
+
require_relative 'piece_type'
|
7
|
+
require_relative 'player'
|
8
|
+
require_relative 'network'
|
9
|
+
require_relative 'client_interface'
|
10
|
+
require 'rexml/document'
|
11
|
+
require 'rexml/streamlistener'
|
12
|
+
require 'builder'
|
13
|
+
|
14
|
+
# This class handles communication to the server over the XML communication
|
15
|
+
# protocol. Messages from the server are parsed and moves are serialized and
|
16
|
+
# send back.
|
17
|
+
class Protocol
|
18
|
+
include Logging
|
19
|
+
include REXML::StreamListener
|
20
|
+
|
21
|
+
# @!attribute [r] gamestate
|
22
|
+
# @return [Gamestate] current gamestate
|
23
|
+
attr_reader :gamestate
|
24
|
+
# @!attribute [rw] roomId
|
25
|
+
# @return [String] current room id
|
26
|
+
attr_accessor :roomId
|
27
|
+
# @!attribute [r] client
|
28
|
+
# @return [ClientInterface] current client
|
29
|
+
attr_reader :client
|
30
|
+
|
31
|
+
def initialize(network, client)
|
32
|
+
@gamestate = GameState.new
|
33
|
+
@network = network
|
34
|
+
@client = client
|
35
|
+
@context = {} # for saving context when stream-parsing the XML
|
36
|
+
@client.gamestate = @gamestate
|
37
|
+
end
|
38
|
+
|
39
|
+
# starts xml-string parsing
|
40
|
+
#
|
41
|
+
# @param text [String] the xml-string that will be parsed
|
42
|
+
def process_string(text)
|
43
|
+
#logger.debug "Parse XML:\n#{text}\n----END XML"
|
44
|
+
begin
|
45
|
+
REXML::Document.parse_stream(text, self)
|
46
|
+
rescue REXML::ParseException => e
|
47
|
+
# to parse incomplete xml, ignore missing end tag exceptions
|
48
|
+
raise e unless e.message =~ /Missing end tag/
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# called when text is encountered
|
53
|
+
def text(text)
|
54
|
+
@context[:last_text] = text
|
55
|
+
end
|
56
|
+
|
57
|
+
# called if an end-tag is read
|
58
|
+
#
|
59
|
+
# @param name [String] the end-tag name, that was read
|
60
|
+
def tag_end(name)
|
61
|
+
case name
|
62
|
+
when 'board'
|
63
|
+
logger.debug @gamestate.board.to_s
|
64
|
+
when 'startTeam'
|
65
|
+
@gamestate.add_player(Player.new(Color::RED, "ONE", 0))
|
66
|
+
@gamestate.add_player(Player.new(Color::BLUE, "TWO", 0))
|
67
|
+
if @context[:last_text] == "ONE"
|
68
|
+
@gamestate.start_team = @gamestate.player_one
|
69
|
+
else
|
70
|
+
@gamestate.start_team = @gamestate.player_two
|
71
|
+
end
|
72
|
+
when 'team'
|
73
|
+
@context[:team] = @context[:last_text]
|
74
|
+
when 'int'
|
75
|
+
if @context[:team] == "ONE"
|
76
|
+
logger.info 'Got player one amber'
|
77
|
+
@gamestate.player_one.amber = @context[:last_text].to_i
|
78
|
+
else
|
79
|
+
logger.info 'Got player two amber'
|
80
|
+
@gamestate.player_two.amber = @context[:last_text].to_i
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# called if a start tag is read
|
86
|
+
# Depending on the tag the gamestate is updated
|
87
|
+
# or the client will be asked for a move
|
88
|
+
#
|
89
|
+
# @param name [String] the start-tag, that was read
|
90
|
+
# @param attrs [Dictionary<String, String>] Attributes attached to the tag
|
91
|
+
def tag_start(name, attrs)
|
92
|
+
case name
|
93
|
+
when 'room'
|
94
|
+
@roomId = attrs['roomId']
|
95
|
+
logger.info 'roomId : ' + @roomId
|
96
|
+
when 'data'
|
97
|
+
logger.debug "data(class) : #{attrs['class']}"
|
98
|
+
@context[:data_class] = attrs['class']
|
99
|
+
if attrs['class'] == 'moveRequest'
|
100
|
+
@client.gamestate = gamestate
|
101
|
+
move = @client.move_requested
|
102
|
+
sendString(move_to_xml(move))
|
103
|
+
end
|
104
|
+
if attrs['class'] == 'error'
|
105
|
+
logger.info "Game ended - ERROR: #{attrs['message']}"
|
106
|
+
@network.disconnect
|
107
|
+
end
|
108
|
+
if attrs['class'] == 'result'
|
109
|
+
logger.info 'Got game result'
|
110
|
+
@network.disconnect
|
111
|
+
@gamestate.condition = Condition.new(nil, '')
|
112
|
+
end
|
113
|
+
when 'state'
|
114
|
+
logger.debug 'new gamestate'
|
115
|
+
@gamestate = GameState.new
|
116
|
+
@gamestate.turn = attrs['turn'].to_i
|
117
|
+
logger.debug "Round: #{@gamestate.round}, Turn: #{@gamestate.turn}"
|
118
|
+
when 'board'
|
119
|
+
logger.debug 'new board'
|
120
|
+
@gamestate.board = Board.new()
|
121
|
+
when 'pieces'
|
122
|
+
@context[:entry] = :pieces
|
123
|
+
when 'coordinates'
|
124
|
+
@context[:x] = attrs['x'].to_i
|
125
|
+
@context[:y] = attrs['y'].to_i
|
126
|
+
when 'piece'
|
127
|
+
x = @context[:x]
|
128
|
+
y = @context[:y]
|
129
|
+
team = Team.find_by_key(attrs['team'].to_sym)
|
130
|
+
type = PieceType.find_by_key(attrs['type'].to_sym)
|
131
|
+
count = attrs['count'].to_i
|
132
|
+
field = Field.new(x, y, Piece.new(team.to_c, type, Coordinates.new(x, y), count))
|
133
|
+
@gamestate.board.add_field(field)
|
134
|
+
when 'from'
|
135
|
+
@context[:from] = Coordinates.new(attrs['x'].to_i, attrs['y'].to_i)
|
136
|
+
when 'to'
|
137
|
+
from = @context[:from]
|
138
|
+
@gamestate.last_move = Move.new(Coordinates.new(from.x, from.y), Coordinates.new(attrs['x'].to_i, attrs['y'].to_i))
|
139
|
+
when 'ambers'
|
140
|
+
@context[:entry] = :ambers
|
141
|
+
when 'winner'
|
142
|
+
# TODO
|
143
|
+
# winning_player = parsePlayer(attrs)
|
144
|
+
# @gamestate.condition = Condition.new(winning_player, @gamestate.condition.reason)
|
145
|
+
when 'score'
|
146
|
+
# TODO
|
147
|
+
# there are two score tags in the result, but reason attribute should be equal on both
|
148
|
+
# @gamestate.condition = Condition.new(@gamestate.condition.winner, attrs['reason'])
|
149
|
+
when 'left'
|
150
|
+
logger.debug 'got left event, terminating'
|
151
|
+
@network.disconnect
|
152
|
+
when 'sc.protocol.responses.CloseConnection'
|
153
|
+
logger.debug 'got left close connection event, terminating'
|
154
|
+
@network.disconnect
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# send a xml document
|
159
|
+
#
|
160
|
+
# @param document [REXML::Document] the document, that will be send to the connected server
|
161
|
+
def sendXml(document)
|
162
|
+
@network.sendXML(document)
|
163
|
+
end
|
164
|
+
|
165
|
+
# send a string
|
166
|
+
#
|
167
|
+
# @param string [String] The string that will be send to the connected server.
|
168
|
+
def sendString(string)
|
169
|
+
@network.sendString("<room roomId=\"#{@roomId}\">#{string}</room>")
|
170
|
+
end
|
171
|
+
|
172
|
+
# converts "this_snake_case" to "thisSnakeCase"
|
173
|
+
def snake_case_to_lower_camel_case(string)
|
174
|
+
string.split('_').inject([]) do |result, e|
|
175
|
+
result + [result.empty? ? e : e.capitalize]
|
176
|
+
end.join
|
177
|
+
end
|
178
|
+
|
179
|
+
# Converts a move to XML for sending to the server.
|
180
|
+
#
|
181
|
+
# @param move [Move] The move to convert to XML.
|
182
|
+
def move_to_xml(move)
|
183
|
+
builder = Builder::XmlMarkup.new(indent: 2)
|
184
|
+
|
185
|
+
if move.nil?
|
186
|
+
raise 'nil moves are not sendable!'
|
187
|
+
end
|
188
|
+
|
189
|
+
# Converting every the move here instead of requiring the Move
|
190
|
+
# class interface to supply a method which returns the XML
|
191
|
+
# because XML-generation should be decoupled from internal data
|
192
|
+
# structures.
|
193
|
+
|
194
|
+
builder.data(class: 'move') do |d|
|
195
|
+
d.from(x: move.from.x, y: move.from.y)
|
196
|
+
d.to(x: move.to.x, y: move.to.y)
|
197
|
+
end
|
198
|
+
|
199
|
+
builder.target!
|
200
|
+
end
|
201
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: software_challenge_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 22.0
|
4
|
+
version: 22.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- 'kwollw '
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: exe
|
12
12
|
cert_chain: []
|
13
|
-
date: 2021-
|
13
|
+
date: 2021-12-07 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: builder
|
@@ -326,7 +326,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
326
326
|
- !ruby/object:Gem::Version
|
327
327
|
version: '0'
|
328
328
|
requirements: []
|
329
|
-
rubygems_version: 3.1.
|
329
|
+
rubygems_version: 3.1.6
|
330
330
|
signing_key:
|
331
331
|
specification_version: 4
|
332
332
|
summary: Provides functions to build a client for the coding competition Software-Challenge
|