veyron/examples/rockpaperscissors: Add command-line player interface.
Add a command-line player interface for humans to play the game. Human
players can either initiate a new game, or wait for someone else to
challenge them.
Also some other minor changes.
Change-Id: If7c664f674f64f2b8cd3230c8ee0cc6d375b00db
diff --git a/examples/rockpaperscissors/common/common.go b/examples/rockpaperscissors/common/common.go
index 5999042..796d8c3 100644
--- a/examples/rockpaperscissors/common/common.go
+++ b/examples/rockpaperscissors/common/common.go
@@ -82,7 +82,7 @@
servers = append(servers, pickBestServer(e.Servers))
}
}
- vlog.Infof("findAll(%q) elapsed: %s", t, time.Now().Sub(start))
+ vlog.VI(1).Infof("findAll(%q) elapsed: %s", t, time.Now().Sub(start))
return servers, nil
}
@@ -118,8 +118,8 @@
for i, r := range score.Rounds {
roundOffset := time.Duration(r.StartTimeNS - score.StartTimeNS)
roundTime := time.Duration(r.EndTimeNS - r.StartTimeNS)
- fmt.Fprintf(buf, "Round %2d: Player 1 played %-10q. Player 2 played %-10q. Winner: %d [%-10s/%-10s]\n",
- i+1, r.Moves[0], r.Moves[1], r.Winner, roundOffset, roundTime)
+ fmt.Fprintf(buf, "Round %2d: Player 1 played %-10q. Player 2 played %-10q. Winner: %d %-28s [%-10s/%-10s]\n",
+ i+1, r.Moves[0], r.Moves[1], r.Winner, r.Comment, roundOffset, roundTime)
}
fmt.Fprintf(buf, "Winner: %d\n", score.Winner)
fmt.Fprintf(buf, "Time: %s\n", time.Duration(score.EndTimeNS-score.StartTimeNS))
diff --git a/examples/rockpaperscissors/impl/impl.go b/examples/rockpaperscissors/impl/impl.go
index b58a9ef..41fd8f6 100644
--- a/examples/rockpaperscissors/impl/impl.go
+++ b/examples/rockpaperscissors/impl/impl.go
@@ -49,9 +49,9 @@
return r.judge.play(names[0], id, stream)
}
-func (r *RPS) Challenge(ctx ipc.ServerContext, address string, id rps.GameID) error {
- vlog.VI(1).Infof("Challenge (%q, %+v) from %s", address, id, ctx.RemoteID())
- return r.player.challenge(address, id)
+func (r *RPS) Challenge(ctx ipc.ServerContext, address string, id rps.GameID, opts rps.GameOptions) error {
+ vlog.VI(1).Infof("Challenge (%q, %+v, %+v) from %s", address, id, opts, ctx.RemoteID())
+ return r.player.challenge(address, id, opts)
}
func (r *RPS) Record(ctx ipc.ServerContext, score rps.ScoreCard) error {
diff --git a/examples/rockpaperscissors/impl/judge.go b/examples/rockpaperscissors/impl/judge.go
index 6dd75a7..9c607b3 100644
--- a/examples/rockpaperscissors/impl/judge.go
+++ b/examples/rockpaperscissors/impl/judge.go
@@ -245,8 +245,8 @@
}
round.Moves[in.player-1] = in.action.Move
}
- round.Winner = j.compareMoves(round.Moves[0], round.Moves[1])
- vlog.VI(1).Infof("Player 1 played %q. Player 2 played %q. Winner: %d", round.Moves[0], round.Moves[1], round.Winner)
+ round.Winner, round.Comment = j.compareMoves(round.Moves[0], round.Moves[1])
+ vlog.VI(1).Infof("Player 1 played %q. Player 2 played %q. Winner: %d %s", round.Moves[0], round.Moves[1], round.Winner, round.Comment)
action = rps.JudgeAction{RoundResult: round}
for _, s := range info.streams {
@@ -299,24 +299,49 @@
return nil
}
-func (j *Judge) compareMoves(m1, m2 string) rps.WinnerTag {
+var moveComments = map[string]string{
+ "lizard-paper": "lizard eats paper",
+ "lizard-rock": "rock crushes lizard",
+ "lizard-scissors": "scissors decapitates lizard",
+ "lizard-spock": "lizard poisons spock",
+ "paper-rock": "paper covers rock",
+ "paper-scissors": "scissors cuts paper",
+ "paper-spock": "paper disproves spock",
+ "rock-scissors": "rock crushes scissors",
+ "rock-spock": "spock vaporizes rock",
+ "scissors-spock": "spock smashes scissors",
+}
+
+func (j *Judge) compareMoves(m1, m2 string) (winner rps.WinnerTag, comment string) {
+ if m1 < m2 {
+ comment = moveComments[m1+"-"+m2]
+ } else {
+ comment = moveComments[m2+"-"+m1]
+ }
if m1 == m2 {
- return rps.Draw
+ winner = rps.Draw
+ return
}
if m1 == "rock" && (m2 == "scissors" || m2 == "lizard") {
- return rps.Player1
+ winner = rps.Player1
+ return
}
if m1 == "paper" && (m2 == "rock" || m2 == "spock") {
- return rps.Player1
+ winner = rps.Player1
+ return
}
if m1 == "scissors" && (m2 == "paper" || m2 == "lizard") {
- return rps.Player1
+ winner = rps.Player1
+ return
}
if m1 == "lizard" && (m2 == "paper" || m2 == "spock") {
- return rps.Player1
+ winner = rps.Player1
+ return
}
if m1 == "spock" && (m2 == "scissors" || m2 == "rock") {
- return rps.Player1
+ winner = rps.Player1
+ return
}
- return rps.Player2
+ winner = rps.Player2
+ return
}
diff --git a/examples/rockpaperscissors/impl/player.go b/examples/rockpaperscissors/impl/player.go
index b800a87..f1b84a1 100644
--- a/examples/rockpaperscissors/impl/player.go
+++ b/examples/rockpaperscissors/impl/player.go
@@ -3,7 +3,6 @@
import (
"io"
"math/rand"
- "sync"
"time"
rps "veyron/examples/rockpaperscissors"
@@ -15,7 +14,6 @@
)
type Player struct {
- lock sync.Mutex
gamesPlayed common.Counter
gamesWon common.Counter
gamesInProgress common.Counter
@@ -44,22 +42,24 @@
vlog.Infof("FindJudge: %v", err)
return err
}
- gameID, err := p.createGame(judge)
+ gameID, gameOpts, err := p.createGame(judge)
if err != nil {
vlog.Infof("createGame: %v", err)
return err
}
vlog.VI(1).Infof("Created gameID %q on %q", gameID, judge)
- opponent, err := common.FindPlayer()
- if err != nil {
- vlog.Infof("FindPlayer: %v", err)
- return err
- }
- vlog.VI(1).Infof("chosen opponent is %q", opponent)
- if err = p.sendChallenge(opponent, judge, gameID); err != nil {
+ for {
+ opponent, err := common.FindPlayer()
+ if err != nil {
+ vlog.Infof("FindPlayer: %v", err)
+ return err
+ }
+ vlog.VI(1).Infof("chosen opponent is %q", opponent)
+ if err = p.sendChallenge(opponent, judge, gameID, gameOpts); err == nil {
+ break
+ }
vlog.Infof("sendChallenge: %v", err)
- return err
}
result, err := p.playGame(judge, gameID)
if err != nil {
@@ -74,29 +74,31 @@
return nil
}
-func (p *Player) createGame(server string) (rps.GameID, error) {
+func (p *Player) createGame(server string) (rps.GameID, rps.GameOptions, error) {
j, err := rps.BindRockPaperScissors(server)
if err != nil {
- return rps.GameID{}, err
+ return rps.GameID{}, rps.GameOptions{}, err
}
numRounds := 3 + rand.Intn(3)
gameType := rps.Classic
if rand.Intn(2) == 1 {
gameType = rps.LizardSpock
}
- return j.CreateGame(rt.R().TODOContext(), rps.GameOptions{NumRounds: int32(numRounds), GameType: gameType})
+ gameOpts := rps.GameOptions{NumRounds: int32(numRounds), GameType: gameType}
+ gameId, err := j.CreateGame(rt.R().TODOContext(), gameOpts)
+ return gameId, gameOpts, err
}
-func (p *Player) sendChallenge(opponent, judge string, gameID rps.GameID) error {
+func (p *Player) sendChallenge(opponent, judge string, gameID rps.GameID, gameOpts rps.GameOptions) error {
o, err := rps.BindRockPaperScissors(opponent)
if err != nil {
return err
}
- return o.Challenge(rt.R().TODOContext(), judge, gameID)
+ return o.Challenge(rt.R().TODOContext(), judge, gameID, gameOpts)
}
// challenge receives an incoming challenge.
-func (p *Player) challenge(judge string, gameID rps.GameID) error {
+func (p *Player) challenge(judge string, gameID rps.GameID, _ rps.GameOptions) error {
vlog.VI(1).Infof("challenge received: %s %v", judge, gameID)
go p.playGame(judge, gameID)
return nil
@@ -139,8 +141,8 @@
}
}
if len(in.RoundResult.Moves[0]) > 0 {
- vlog.VI(1).Infof("Player 1 played %q. Player 2 played %q. Winner: %v",
- in.RoundResult.Moves[0], in.RoundResult.Moves[1], in.RoundResult.Winner)
+ vlog.VI(1).Infof("Player 1 played %q. Player 2 played %q. Winner: %v %s",
+ in.RoundResult.Moves[0], in.RoundResult.Moves[1], in.RoundResult.Winner, in.RoundResult.Comment)
}
if len(in.Score.Players) > 0 {
vlog.VI(1).Infof("Score card: %s", common.FormatScoreCard(in.Score))
diff --git a/examples/rockpaperscissors/rpsplayercli/main.go b/examples/rockpaperscissors/rpsplayercli/main.go
new file mode 100644
index 0000000..092dc3f
--- /dev/null
+++ b/examples/rockpaperscissors/rpsplayercli/main.go
@@ -0,0 +1,325 @@
+// rpsplayer is a command-line implementation of the Player service that allows
+// a human player to join the game.
+package main
+
+import (
+ "errors"
+ "flag"
+ "fmt"
+ "io"
+ "os"
+ "sort"
+ "strings"
+ "sync"
+ "time"
+
+ rps "veyron/examples/rockpaperscissors"
+ "veyron/examples/rockpaperscissors/common"
+ sflag "veyron/security/flag"
+
+ "veyron2"
+ "veyron2/ipc"
+ "veyron2/rt"
+ "veyron2/vlog"
+)
+
+var (
+ // TODO(rthellend): Remove the address and protocol flags when the config manager is working.
+ protocol = flag.String("protocol", "tcp", "network to listen on. For example, set to 'veyron' and set --address to the endpoint/name of a proxy to have this service proxied.")
+ address = flag.String("address", ":0", "address to listen on")
+)
+
+func main() {
+ r := rt.Init()
+ defer r.Shutdown()
+ for {
+ if selectOne([]string{"Initiate Game", "Wait For Challenge"}) == 0 {
+ initiateGame()
+ } else {
+ fmt.Println("Waiting to receive a challenge...")
+ game := recvChallenge(r)
+ playGame(game.address, game.id)
+ }
+ if selectOne([]string{"Play Again", "Quit"}) == 1 {
+ break
+ }
+ }
+}
+
+type gameChallenge struct {
+ address string
+ id rps.GameID
+ opts rps.GameOptions
+}
+
+// impl is a PlayerService implementation that prompts the user to accept or
+// decline challenges. While waiting for a reply from the user, any incoming
+// challenges are auto-declined.
+type impl struct {
+ ch chan gameChallenge
+ decline bool
+ lock sync.Mutex
+}
+
+func (i *impl) setDecline(v bool) bool {
+ i.lock.Lock()
+ defer i.lock.Unlock()
+ prev := i.decline
+ i.decline = v
+ return prev
+}
+
+func (i *impl) Challenge(ctx ipc.ServerContext, address string, id rps.GameID, opts rps.GameOptions) error {
+ vlog.VI(1).Infof("Challenge (%q, %+v) from %s", address, id, ctx.RemoteID())
+ // When setDecline(true) returns, future challenges will be declined.
+ // Whether the current challenge should be considered depends on the
+ // previous state. If 'decline' was already true, we need to decline
+ // this challenge. It 'decline' was false, this is the first challenge
+ // that we should process.
+ if i.setDecline(true) {
+ return errors.New("player is busy")
+ }
+ fmt.Println()
+ fmt.Printf("Challenge received from %s for a %d-round ", ctx.RemoteID(), opts.NumRounds)
+ switch opts.GameType {
+ case rps.Classic:
+ fmt.Print("Classic ")
+ case rps.LizardSpock:
+ fmt.Print("Lizard-Spock ")
+ default:
+ }
+ fmt.Println("Game.")
+ if selectOne([]string{"Accept", "Decline"}) == 0 {
+ i.ch <- gameChallenge{address, id, opts}
+ return nil
+ }
+ // Start considering challenges again.
+ i.setDecline(false)
+ return errors.New("player declined challenge")
+}
+
+// recvChallenge runs a server until a game challenge is accepted by the user.
+// The server is stopped afterwards.
+func recvChallenge(rt veyron2.Runtime) gameChallenge {
+ server, err := rt.NewServer()
+ if err != nil {
+ vlog.Fatalf("NewServer failed: %v", err)
+ }
+ ch := make(chan gameChallenge)
+
+ if err := server.Register("", ipc.SoloDispatcher(rps.NewServerPlayer(&impl{ch: ch}), sflag.NewAuthorizerOrDie())); err != nil {
+ vlog.Fatalf("Register failed: %v", err)
+ }
+ ep, err := server.Listen(*protocol, *address)
+ if err != nil {
+ vlog.Fatalf("Listen(%q, %q) failed: %v", "tcp", *address, err)
+ }
+ hostname, err := os.Hostname()
+ if err != nil {
+ vlog.Fatalf("os.Hostname failed: %v", err)
+ }
+ if err := server.Publish(fmt.Sprintf("rps/player/%s@%s", os.Getenv("USER"), hostname)); err != nil {
+ vlog.Fatalf("Publish failed: %v", err)
+ }
+ vlog.Infof("Listening on endpoint /%s", ep)
+ result := <-ch
+ server.Stop()
+ return result
+}
+
+// initiateGame initiates a new game by getting a list of judges and players,
+// and asking the user to select one of each, to select the game options, what
+// to play, etc.
+func initiateGame() error {
+ jChan := make(chan findResult)
+ oChan := make(chan findResult)
+ go findAll("judge", jChan)
+ go findAll("player", oChan)
+
+ fmt.Println("Looking for available participants...")
+ judges := <-jChan
+ opponents := <-oChan
+ fmt.Println()
+ if len(judges.names) == 0 || len(opponents.names) == 0 {
+ return errors.New("no one to play with")
+ }
+
+ fmt.Println("Choose a judge:")
+ j := selectOne(judges.names)
+ fmt.Println("Choose an opponent:")
+ o := selectOne(opponents.names)
+ fmt.Println("Choose the type of rock-paper-scissors game would you like to play:")
+ gameType := selectOne([]string{"Classic", "LizardSpock"})
+ fmt.Println("Choose the number of rounds required to win:")
+ numRounds := selectOne([]string{"1", "2", "3", "4", "5", "6"}) + 1
+ gameOpts := rps.GameOptions{NumRounds: int32(numRounds), GameType: rps.GameTypeTag(gameType)}
+
+ gameID, err := createGame(judges.servers[j], gameOpts)
+ if err != nil {
+ vlog.Infof("createGame: %v", err)
+ return err
+ }
+ for {
+ err := sendChallenge(opponents.servers[o], judges.servers[j], gameID, gameOpts)
+ if err == nil {
+ break
+ }
+ fmt.Printf("Challenge was declined by %s (%v)\n", opponents.names[o], err)
+ fmt.Println("Choose another opponent:")
+ o = selectOne(opponents.names)
+ }
+ fmt.Println("Joining the game...")
+ if _, err = playGame(judges.servers[j], gameID); err != nil {
+ vlog.Infof("playGame: %v", err)
+ return err
+ }
+ return nil
+}
+
+func createGame(server string, opts rps.GameOptions) (rps.GameID, error) {
+ j, err := rps.BindRockPaperScissors(server)
+ if err != nil {
+ return rps.GameID{}, err
+ }
+ return j.CreateGame(rt.R().TODOContext(), opts)
+}
+
+func sendChallenge(opponent, judge string, gameID rps.GameID, gameOpts rps.GameOptions) error {
+ o, err := rps.BindRockPaperScissors(opponent)
+ if err != nil {
+ return err
+ }
+ return o.Challenge(rt.R().TODOContext(), judge, gameID, gameOpts)
+}
+
+func playGame(judge string, gameID rps.GameID) (rps.PlayResult, error) {
+ fmt.Println()
+ j, err := rps.BindRockPaperScissors(judge)
+ if err != nil {
+ return rps.PlayResult{}, err
+ }
+ game, err := j.Play(rt.R().TODOContext(), gameID, veyron2.CallTimeout(10*time.Minute))
+ if err != nil {
+ return rps.PlayResult{}, err
+ }
+ var playerNum int32
+ for {
+ in, err := game.Recv()
+ if err == io.EOF {
+ fmt.Println("Game Ended")
+ break
+ }
+ if err != nil {
+ vlog.Infof("recv error: %v", err)
+ break
+ }
+ if in.PlayerNum > 0 {
+ playerNum = in.PlayerNum
+ fmt.Printf("You are player %d\n", in.PlayerNum)
+ }
+ if len(in.OpponentName) > 0 {
+ fmt.Printf("Your opponent is %q\n", in.OpponentName)
+ }
+ if len(in.RoundResult.Moves[0]) > 0 {
+ if playerNum != 1 && playerNum != 2 {
+ vlog.Fatalf("invalid playerNum: %d", playerNum)
+ }
+ fmt.Printf("You played %q\n", in.RoundResult.Moves[playerNum-1])
+ fmt.Printf("Your opponent played %q\n", in.RoundResult.Moves[2-playerNum])
+ if len(in.RoundResult.Comment) > 0 {
+ fmt.Printf(">>> %s <<<\n", strings.ToUpper(in.RoundResult.Comment))
+ }
+ if in.RoundResult.Winner == 0 {
+ fmt.Println("----- It's a draw -----")
+ } else if rps.WinnerTag(playerNum) == in.RoundResult.Winner {
+ fmt.Println("***** You WIN *****")
+ } else {
+ fmt.Println("##### You LOSE #####")
+ }
+ }
+ if len(in.MoveOptions) > 0 {
+ fmt.Println()
+ fmt.Println("Choose your weapon:")
+ m := selectOne(in.MoveOptions)
+ if err := game.Send(rps.PlayerAction{Move: in.MoveOptions[m]}); err != nil {
+ return rps.PlayResult{}, err
+ }
+ }
+ if len(in.Score.Players) > 0 {
+ fmt.Println()
+ fmt.Println("==== GAME SUMMARY ====")
+ fmt.Print(common.FormatScoreCard(in.Score))
+ fmt.Println("======================")
+ if rps.WinnerTag(playerNum) == in.Score.Winner {
+ fmt.Println("You won! :)")
+ } else {
+ fmt.Println("You lost! :(")
+ }
+ }
+ }
+ return game.Finish()
+}
+
+func selectOne(choices []string) (choice int) {
+ if len(choices) == 0 {
+ vlog.Fatal("No options to choose from!")
+ }
+ fmt.Println()
+ for i, x := range choices {
+ fmt.Printf(" %d. %s\n", i+1, x)
+ }
+ fmt.Println()
+ for {
+ if len(choices) == 1 {
+ fmt.Print("Select one [1] --> ")
+ } else {
+ fmt.Printf("Select one [1-%d] --> ", len(choices))
+ }
+ fmt.Scanf("%d", &choice)
+ if choice >= 1 && choice <= len(choices) {
+ choice -= 1
+ break
+ }
+ }
+ fmt.Println()
+ return
+}
+
+type findResult struct {
+ names []string
+ servers []string
+}
+
+// byName implements sort.Interface for findResult.
+type byName findResult
+
+func (n byName) Len() int {
+ return len(n.names)
+}
+func (n byName) Swap(i, j int) {
+ n.names[i], n.names[j] = n.names[j], n.names[i]
+ n.servers[i], n.servers[j] = n.servers[j], n.servers[i]
+}
+func (n byName) Less(i, j int) bool {
+ return n.names[i] < n.names[j]
+}
+
+func findAll(t string, out chan findResult) {
+ ns := rt.R().Namespace()
+ var result findResult
+ c, err := ns.Glob(rt.R().TODOContext(), "rps/"+t+"/*")
+ if err != nil {
+ vlog.Infof("ns.Glob failed: %v", err)
+ out <- result
+ return
+ }
+ for e := range c {
+ fmt.Print(".")
+ if len(e.Servers) > 0 {
+ result.names = append(result.names, e.Name)
+ result.servers = append(result.servers, e.Servers[0].Server)
+ }
+ }
+ sort.Sort(byName(result))
+ out <- result
+}
diff --git a/examples/rockpaperscissors/service.vdl b/examples/rockpaperscissors/service.vdl
index 4af66e9..1b927b9 100644
--- a/examples/rockpaperscissors/service.vdl
+++ b/examples/rockpaperscissors/service.vdl
@@ -59,6 +59,7 @@
// Round represents the state of a round.
type Round struct {
Moves [2]string // Each player's move.
+ Comment string // A text comment from judge about the round.
Winner WinnerTag // Who won the round.
StartTimeNS int64 // The time at which the round started.
EndTimeNS int64 // The time at which the round ended.
@@ -82,7 +83,7 @@
type Player interface {
// Challenge is used by other players to challenge this player to a game. If
// the challenge is accepted, the method returns nil.
- Challenge(Address string, ID GameID) error
+ Challenge(Address string, ID GameID, Opts GameOptions) error
}
// ScoreKeeper receives the outcome of games from Judges.
diff --git a/examples/rockpaperscissors/service.vdl.go b/examples/rockpaperscissors/service.vdl.go
index 1d9354d..946d6e7 100644
--- a/examples/rockpaperscissors/service.vdl.go
+++ b/examples/rockpaperscissors/service.vdl.go
@@ -43,6 +43,7 @@
// Round represents the state of a round.
type Round struct {
Moves [2]string // Each player's move.
+ Comment string // A text comment from judge about the round.
Winner WinnerTag // Who won the round.
StartTimeNS int64 // The time at which the round started.
EndTimeNS int64 // The time at which the round ended.
@@ -351,6 +352,7 @@
_gen_wiretype.ArrayType{Elem: 0x3, Len: 0x2, Name: "", Tags: []string(nil)}, _gen_wiretype.NamedPrimitiveType{Type: 0x32, Name: "veyron/examples/rockpaperscissors.WinnerTag", Tags: []string(nil)}, _gen_wiretype.StructType{
[]_gen_wiretype.FieldType{
_gen_wiretype.FieldType{Type: 0x47, Name: "Moves"},
+ _gen_wiretype.FieldType{Type: 0x3, Name: "Comment"},
_gen_wiretype.FieldType{Type: 0x48, Name: "Winner"},
_gen_wiretype.FieldType{Type: 0x25, Name: "StartTimeNS"},
_gen_wiretype.FieldType{Type: 0x25, Name: "EndTimeNS"},
@@ -417,7 +419,7 @@
type Player_ExcludingUniversal interface {
// Challenge is used by other players to challenge this player to a game. If
// the challenge is accepted, the method returns nil.
- Challenge(ctx _gen_context.T, Address string, ID GameID, opts ..._gen_ipc.CallOpt) (err error)
+ Challenge(ctx _gen_context.T, Address string, ID GameID, Opts GameOptions, opts ..._gen_ipc.CallOpt) (err error)
}
type Player interface {
_gen_ipc.UniversalServiceMethods
@@ -429,7 +431,7 @@
// Challenge is used by other players to challenge this player to a game. If
// the challenge is accepted, the method returns nil.
- Challenge(context _gen_ipc.ServerContext, Address string, ID GameID) (err error)
+ Challenge(context _gen_ipc.ServerContext, Address string, ID GameID, Opts GameOptions) (err error)
}
// BindPlayer returns the client stub implementing the Player
@@ -475,9 +477,9 @@
name string
}
-func (__gen_c *clientStubPlayer) Challenge(ctx _gen_context.T, Address string, ID GameID, opts ..._gen_ipc.CallOpt) (err error) {
+func (__gen_c *clientStubPlayer) Challenge(ctx _gen_context.T, Address string, ID GameID, Opts GameOptions, opts ..._gen_ipc.CallOpt) (err error) {
var call _gen_ipc.Call
- if call, err = __gen_c.client.StartCall(ctx, __gen_c.name, "Challenge", []interface{}{Address, ID}, opts...); err != nil {
+ if call, err = __gen_c.client.StartCall(ctx, __gen_c.name, "Challenge", []interface{}{Address, ID, Opts}, opts...); err != nil {
return
}
if ierr := call.Finish(&err); ierr != nil {
@@ -544,9 +546,10 @@
InArgs: []_gen_ipc.MethodArgument{
{Name: "Address", Type: 3},
{Name: "ID", Type: 65},
+ {Name: "Opts", Type: 67},
},
OutArgs: []_gen_ipc.MethodArgument{
- {Name: "", Type: 66},
+ {Name: "", Type: 68},
},
}
@@ -556,6 +559,12 @@
_gen_wiretype.FieldType{Type: 0x3, Name: "ID"},
},
"veyron/examples/rockpaperscissors.GameID", []string(nil)},
+ _gen_wiretype.NamedPrimitiveType{Type: 0x32, Name: "veyron/examples/rockpaperscissors.GameTypeTag", Tags: []string(nil)}, _gen_wiretype.StructType{
+ []_gen_wiretype.FieldType{
+ _gen_wiretype.FieldType{Type: 0x24, Name: "NumRounds"},
+ _gen_wiretype.FieldType{Type: 0x42, Name: "GameType"},
+ },
+ "veyron/examples/rockpaperscissors.GameOptions", []string(nil)},
_gen_wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}}
return result, nil
@@ -579,8 +588,8 @@
return
}
-func (__gen_s *ServerStubPlayer) Challenge(call _gen_ipc.ServerCall, Address string, ID GameID) (err error) {
- err = __gen_s.service.Challenge(call, Address, ID)
+func (__gen_s *ServerStubPlayer) Challenge(call _gen_ipc.ServerCall, Address string, ID GameID, Opts GameOptions) (err error) {
+ err = __gen_s.service.Challenge(call, Address, ID, Opts)
return
}
@@ -728,6 +737,7 @@
_gen_wiretype.ArrayType{Elem: 0x3, Len: 0x2, Name: "", Tags: []string(nil)}, _gen_wiretype.NamedPrimitiveType{Type: 0x32, Name: "veyron/examples/rockpaperscissors.WinnerTag", Tags: []string(nil)}, _gen_wiretype.StructType{
[]_gen_wiretype.FieldType{
_gen_wiretype.FieldType{Type: 0x43, Name: "Moves"},
+ _gen_wiretype.FieldType{Type: 0x3, Name: "Comment"},
_gen_wiretype.FieldType{Type: 0x44, Name: "Winner"},
_gen_wiretype.FieldType{Type: 0x25, Name: "StartTimeNS"},
_gen_wiretype.FieldType{Type: 0x25, Name: "EndTimeNS"},