From 875be2bc3d679611d4b111db2f10fe4dd57b8584 Mon Sep 17 00:00:00 2001 From: Benjamin Payne Date: Wed, 9 Nov 2022 21:52:41 -0700 Subject: [PATCH 01/12] Fixes wh_test for It would be interesting to actually check the response for this test. --- go.mod | 2 +- internal/handler/games/wh.go | 2 +- internal/handler/games/wh_test.go | 68 +++++++++++++++---------------- 3 files changed, 36 insertions(+), 36 deletions(-) diff --git a/go.mod b/go.mod index a12408d..6802106 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/google/uuid v1.3.0 github.com/mattermost/mattermost-server/v6 v6.7.2 github.com/mitchellh/mapstructure v1.4.2 + github.com/opentracing/opentracing-go v1.2.0 github.com/quibbble/go-boardgame v1.0.2 github.com/tkanos/gonfig v0.0.0-20210106201359-53e13348de2f golang.org/x/exp v0.0.0-20221012134508-3640c57a48ea @@ -35,7 +36,6 @@ require ( github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pborman/uuid v1.2.1 // indirect github.com/pelletier/go-toml v1.9.4 // indirect github.com/philhofer/fwd v1.1.1 // indirect diff --git a/internal/handler/games/wh.go b/internal/handler/games/wh.go index 13fa80c..fa75531 100644 --- a/internal/handler/games/wh.go +++ b/internal/handler/games/wh.go @@ -331,7 +331,7 @@ func handleGameWithDirective(event BotGame, err error) (error, bool) { winner, err := getWHWinner(g) if err == nil { - response.Message = fmt.Sprintf("%s has won the game of waving hands.", winner.Name) + response.Message = fmt.Sprintf("/echo %s \"has won the game of waving hands.\" 2", winner.Name) event.ResponseChannel <- response ClearGame(g.Channel.Id, event.Cache) diff --git a/internal/handler/games/wh_test.go b/internal/handler/games/wh_test.go index b90d43b..f7548ba 100644 --- a/internal/handler/games/wh_test.go +++ b/internal/handler/games/wh_test.go @@ -1,8 +1,10 @@ package games import ( + "fmt" "github.com/mattermost/mattermost-server/v6/model" "github.com/pyrousnet/pyrous-gobot/internal/cache" + "github.com/pyrousnet/pyrous-gobot/internal/comms" "reflect" "testing" ) @@ -12,64 +14,62 @@ func Test_handleEmptyBody(t *testing.T) { event BotGame response Response } + rs := make(chan comms.Response) tests := []struct { name string args args - want Response - want1 error - want2 bool + want error + want1 bool }{ { name: "empty input", args: args{ event: BotGame{ - body: "", - sender: "", - target: "", - mm: nil, - settings: nil, - ReplyChannel: &model.Channel{Id: "test"}, - method: Method{}, - cache: &cache.MockCache{}, + body: "", + sender: "", + target: "", + mm: nil, + settings: nil, + ReplyChannel: &model.Channel{Id: "test"}, + ResponseChannel: rs, + method: Method{}, + Cache: &cache.MockCache{}, }, }, - want: Response{ - Message: "player is missing a name", - Type: "dm", - }, - want1: nil, - want2: true, + want: nil, + want1: true, }, { name: "", args: args{ event: BotGame{ - body: "", - sender: "test", - target: "", - mm: nil, - settings: nil, - ReplyChannel: &model.Channel{Id: "test"}, - method: Method{}, - cache: &cache.MockCache{}, + body: "", + sender: "test", + target: "", + mm: nil, + settings: nil, + ReplyChannel: &model.Channel{Id: "test"}, + ResponseChannel: rs, + method: Method{}, + Cache: &cache.MockCache{}, }, }, - want: Response{ - Message: "/echo test would like to play a game of Waving Hands.\n", - }, + want: nil, + want1: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, got1, got2 := handleEmptyBody(tt.args.event, tt.args.response) + go func() { + got2 := <-rs + fmt.Println(got2) + }() + got, got1 := handleEmptyBody(tt.args.event) if !reflect.DeepEqual(got, tt.want) { t.Errorf("handleEmptyBody() got = %v, want %v", got, tt.want) } - if !reflect.DeepEqual(got1, tt.want1) { - t.Errorf("handleEmptyBody() got1 = %v, want %v", got1, tt.want1) - } - if got2 != tt.want2 { - t.Errorf("handleEmptyBody() got2 = %v, want %v", got2, tt.want2) + if got1 != tt.want1 { + t.Errorf("handleEmptyBody() got2 = %v, want %v", got1, tt.want1) } }) } From 1fbbab8efe7e2c87f74f74dc13fb0e683a98a190 Mon Sep 17 00:00:00 2001 From: Benjamin Payne Date: Fri, 11 Nov 2022 09:55:31 -0700 Subject: [PATCH 02/12] Fixes waving hands tests. The issue was that the test needed to be run in the go routine and the channel needed to be handled in the main rountine's test. --- internal/handler/games/wh_test.go | 37 ++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/internal/handler/games/wh_test.go b/internal/handler/games/wh_test.go index f7548ba..07c6bf1 100644 --- a/internal/handler/games/wh_test.go +++ b/internal/handler/games/wh_test.go @@ -1,7 +1,6 @@ package games import ( - "fmt" "github.com/mattermost/mattermost-server/v6/model" "github.com/pyrousnet/pyrous-gobot/internal/cache" "github.com/pyrousnet/pyrous-gobot/internal/comms" @@ -20,6 +19,7 @@ func Test_handleEmptyBody(t *testing.T) { args args want error want1 bool + want2 comms.Response }{ { name: "empty input", @@ -38,9 +38,16 @@ func Test_handleEmptyBody(t *testing.T) { }, want: nil, want1: true, + want2: comms.Response{ + ReplyChannelId: "test", + Message: "player is missing a name", + Type: "dm", + UserId: "", + Quit: nil, + }, }, { - name: "", + name: "test body", args: args{ event: BotGame{ body: "", @@ -56,20 +63,30 @@ func Test_handleEmptyBody(t *testing.T) { }, want: nil, want1: false, + want2: comms.Response{ + ReplyChannelId: "test", + Message: "/echo test would like to play a game of Waving Hands.\n", + Type: "command", + UserId: "", + Quit: nil, + }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { go func() { - got2 := <-rs - fmt.Println(got2) + got, got1 := handleEmptyBody(tt.args.event) + if got != tt.want { + t.Errorf("handleEmptyBody() got = %v, want %v", got1, tt.want1) + } + + if got1 != tt.want1 { + t.Errorf("handleEmptyBody() got1 = %v, want1 %v", got1, tt.want1) + } }() - got, got1 := handleEmptyBody(tt.args.event) - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("handleEmptyBody() got = %v, want %v", got, tt.want) - } - if got1 != tt.want1 { - t.Errorf("handleEmptyBody() got2 = %v, want %v", got1, tt.want1) + got2 := <-rs + if !reflect.DeepEqual(got2, tt.want2) { + t.Errorf("handleEmptyBody() got2 = %v, want2 %v", got2, tt.want2) } }) } From 05ae21a9e989c4a5556a51c3e15b78d6966450a7 Mon Sep 17 00:00:00 2001 From: Benjamin Payne Date: Sat, 12 Nov 2022 12:50:32 -0700 Subject: [PATCH 03/12] Fixes issues with casting spells. Started testing game dynamics. --- .../wavinghands/spells/cause-heavy-wounds.go | 26 +++++--- .../wavinghands/spells/cure-heavy-wounds.go | 30 ++++++--- .../games/wavinghands/spells/missile.go | 61 +++++++++++++++++++ internal/handler/games/wh.go | 23 +++++-- 4 files changed, 121 insertions(+), 19 deletions(-) create mode 100644 internal/handler/games/wavinghands/spells/missile.go diff --git a/internal/handler/games/wavinghands/spells/cause-heavy-wounds.go b/internal/handler/games/wavinghands/spells/cause-heavy-wounds.go index bee75c0..464337d 100644 --- a/internal/handler/games/wavinghands/spells/cause-heavy-wounds.go +++ b/internal/handler/games/wavinghands/spells/cause-heavy-wounds.go @@ -18,19 +18,31 @@ type CauseHeavyWounds struct { } func (cHW CauseHeavyWounds) Cast(wizard *wavinghands.Wizard, target *wavinghands.Living) (string, error) { - if (len(wizard.Right.Sequence) >= len(cHW.Sequence) && strings.HasSuffix(wizard.Right.Sequence, cHW.Sequence)) || - (len(wizard.Left.Sequence) >= len(cHW.Sequence) && strings.HasSuffix(wizard.Left.Sequence, cHW.ShSequence)) { + var returnString string = "" + if strings.HasSuffix(wizard.Right.Sequence, cHW.Sequence) { if strings.Contains(target.Wards, "cureHeavyWounds") { - target.HitPoints -= 1 - return fmt.Sprintf("%s caused heavy wounds on %s but they were protected and only sustained minimal damage", wizard.Name, target.Selector), nil + target.HitPoints -= cHW.Damage - 2 + returnString = fmt.Sprintf("%s caused heavy wounds on %s but they were protected and only sustained minimal damage", wizard.Name, target.Selector) } else { - target.HitPoints -= 3 - return fmt.Sprintf("%s caused heavy wounds on %s", wizard.Name, target.Selector), nil + target.HitPoints -= cHW.Damage + returnString = fmt.Sprintf("%s caused heavy wounds on %s", wizard.Name, target.Selector) + } + } + if strings.HasSuffix(wizard.Left.Sequence, cHW.Sequence) { + if returnString != "" { + returnString = returnString + "\n" + } + if strings.Contains(target.Wards, "cureHeavyWounds") { + target.HitPoints -= cHW.Damage - 2 + returnString += fmt.Sprintf("%s caused heavy wounds on %s but they were protected and only sustained minimal damage", wizard.Name, target.Selector) + } else { + target.HitPoints -= cHW.Damage + returnString += fmt.Sprintf("%s caused heavy wounds on %s", wizard.Name, target.Selector) } } - return "", nil + return returnString, nil } func GetCauseHeavyWoundsSpell(s *wavinghands.Spell, e error) (*CauseHeavyWounds, error) { if e != nil { diff --git a/internal/handler/games/wavinghands/spells/cure-heavy-wounds.go b/internal/handler/games/wavinghands/spells/cure-heavy-wounds.go index bfa9822..af362db 100644 --- a/internal/handler/games/wavinghands/spells/cure-heavy-wounds.go +++ b/internal/handler/games/wavinghands/spells/cure-heavy-wounds.go @@ -19,16 +19,26 @@ type CureHeavyWounds struct { } func (cHW CureHeavyWounds) Cast(wizard *wavinghands.Wizard, target *wavinghands.Living) (string, error) { - if (len(wizard.Right.Sequence) >= len(cHW.Sequence) && strings.HasSuffix(wizard.Right.Sequence, cHW.Sequence)) || - (len(wizard.Left.Sequence) >= len(cHW.Sequence) && strings.HasSuffix(wizard.Left.Sequence, cHW.ShSequence)) { + var returnString string = "" + if strings.HasSuffix(wizard.Right.Sequence, cHW.Sequence) { wards := strings.Split(target.Wards, ",") wards = append(wards, "cureHeavyWounds") // Lasts one round target.Wards = strings.Join(wards, ",") - return fmt.Sprintf("%s has cast Cure Heavy Wounds on %s", wizard.Name, target.Selector), nil + returnString += fmt.Sprintf("%s has cast Cure Heavy Wounds on %s", wizard.Name, target.Selector) + } + if strings.HasSuffix(wizard.Left.Sequence, cHW.Sequence) { + if returnString != "" { + returnString += "\n" + } + wards := strings.Split(target.Wards, ",") + wards = append(wards, "cureHeavyWounds") // Lasts one round + target.Wards = strings.Join(wards, ",") + + returnString += fmt.Sprintf("%s has cast Cure Heavy Wounds on %s", wizard.Name, target.Selector) } - return "", nil + return returnString, nil } func GetCureHeavyWoundsSpell(s *wavinghands.Spell, e error) (*CureHeavyWounds, error) { @@ -48,10 +58,16 @@ func GetCureHeavyWoundsSpell(s *wavinghands.Spell, e error) (*CureHeavyWounds, e }, nil } -func (cHW CureHeavyWounds) clear(target *wavinghands.Living) error { +func (cHW CureHeavyWounds) Clear(target *wavinghands.Living) error { wards := strings.Split(target.Wards, ",") idx := slices.Index(wards, "cureHeavyWounds") - wavinghands.Remove(wards, idx) - target.Wards = strings.Join(wards, ",") + if idx >= 0 { + wavinghands.Remove(wards, idx) + } + if len(wards) > 0 { + target.Wards = strings.Join(wards, ",") + } else { + target.Wards = "" + } return nil } diff --git a/internal/handler/games/wavinghands/spells/missile.go b/internal/handler/games/wavinghands/spells/missile.go new file mode 100644 index 0000000..9268a15 --- /dev/null +++ b/internal/handler/games/wavinghands/spells/missile.go @@ -0,0 +1,61 @@ +package spells + +import ( + "fmt" + "github.com/pyrousnet/pyrous-gobot/internal/handler/games/wavinghands" + "strings" +) + +type Missile struct { + Name string `json:"name"` + Sequence string `json:"sequence"` + ShSequence string `json:"sh-sequence"` + Description string `json:"description"` + Usage string `json:"usage"` + Damage int `json:"damage"` + Resistences string `json:"resistences"` + Protections string `json:"protections"` +} + +func (m Missile) Cast(wizard *wavinghands.Wizard, target *wavinghands.Living) (string, error) { + var returnString string = "" + if strings.HasSuffix(wizard.Right.Sequence, m.Sequence) { + + if strings.Contains(target.Wards, "shield") { + returnString += fmt.Sprintf("%s cast a missile at %s but they were protected by a shield and took no damage", wizard.Name, target.Selector) + } else { + target.HitPoints -= m.Damage + returnString += fmt.Sprintf("%s cast a missile at %s", wizard.Name, target.Selector) + } + } + if strings.HasSuffix(wizard.Left.Sequence, m.Sequence) { + if returnString != "" { + returnString += "\n" + } + if strings.Contains(target.Wards, "shield") { + returnString += fmt.Sprintf("%s cast a missile at %s but they were protected by a shield and took no damage", wizard.Name, target.Selector) + } else { + target.HitPoints -= m.Damage + returnString += fmt.Sprintf("%s cast a missile at %s", wizard.Name, target.Selector) + } + } + + return returnString, nil +} + +func GetMissileSpell(s *wavinghands.Spell, e error) (*Missile, error) { + if e != nil { + return &Missile{}, e + } + + return &Missile{ + Name: s.Name, + Sequence: s.Sequence, + ShSequence: s.ShSequence, + Description: s.Description, + Usage: s.Usage, + Damage: s.Damage, + Resistences: s.Resistances, + Protections: s.Protections, + }, nil +} diff --git a/internal/handler/games/wh.go b/internal/handler/games/wh.go index fa75531..552c1b6 100644 --- a/internal/handler/games/wh.go +++ b/internal/handler/games/wh.go @@ -250,10 +250,6 @@ func handleGameWithDirective(event BotGame, err error) (error, bool) { g := Game{gData: wHGameData, Channel: channel} p, err := GetCurrentPlayer(g, name) - if target != "" { - t, err = FindTarget(g, target) - } - if err != nil { return err, true } else { @@ -284,12 +280,14 @@ func handleGameWithDirective(event BotGame, err error) (error, bool) { for i, p := range g.gData.Players { rG := p.Right.GetAt(len(p.Right.Sequence) - 1) lG := p.Left.GetAt(len(p.Left.Sequence) - 1) + if p.Target != "" { + t, err = FindTarget(g, p.Target) + } announceGestures(&p, event.ResponseChannel, response, string(rG), string(lG), p.GetTarget()) sr, err := spells.GetSurrenderSpell(wavinghands.GetSpell("Surrender")) if err != nil { return err, true } - t = &p.Living surrenderString, err := sr.Cast(&g.gData.Players[i], t) if err == nil && surrenderString != "" { response.Message = surrenderString @@ -312,6 +310,17 @@ func handleGameWithDirective(event BotGame, err error) (error, bool) { } // Run Damage Spells + m, mErr := spells.GetMissileSpell(wavinghands.GetSpell("Missile")) + if mErr != nil { + return mErr, true + } + mResult, err := m.Cast(&g.gData.Players[i], t) + if err == nil && mResult != "" { + response.Message = mResult + event.ResponseChannel <- response + } else if err != nil { + return err, true + } CHW, err := spells.GetCauseHeavyWoundsSpell(wavinghands.GetSpell("Cause Heavy Wounds")) if err != nil { return err, true @@ -323,6 +332,8 @@ func handleGameWithDirective(event BotGame, err error) (error, bool) { } else if err != nil { return err, true } + + cHW.Clear(&p.Living) } // Run Summon Spells @@ -447,6 +458,8 @@ func FindTarget(g Game, selector string) (*wavinghands.Living, error) { for i, w := range g.gData.Players { if w.Name == name { wizard = &g.gData.Players[i] + } else { + continue } if monster == "" { From da08bdf894f01897d4a9c6654d4316a6f4413cf4 Mon Sep 17 00:00:00 2001 From: Benjamin Payne Date: Mon, 14 Nov 2022 20:50:42 -0700 Subject: [PATCH 04/12] Fixes issue with starting waving hands game. --- internal/handler/games/wh.go | 23 +++++++++++++++++------ internal/users/users.go | 14 ++++++++------ 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/internal/handler/games/wh.go b/internal/handler/games/wh.go index 552c1b6..b0dd8e8 100644 --- a/internal/handler/games/wh.go +++ b/internal/handler/games/wh.go @@ -100,7 +100,7 @@ func StartWavingHands(event BotGame) (Game, error) { if !inGame { return Game{}, fmt.Errorf("player not active in game, cannot start") } - if len(g.gData.Players) > wavinghands.GetMinTeams() && len(g.gData.Players) <= wavinghands.GetMaxTeams() { + if len(g.gData.Players) >= wavinghands.GetMinTeams() && len(g.gData.Players) <= wavinghands.GetMaxTeams() { g.gData.State = "playing" } else if len(g.gData.Players) < wavinghands.GetMinTeams() { return Game{}, fmt.Errorf("not enough players to start the game") @@ -235,6 +235,12 @@ func handleGameWithDirective(event BotGame, err error) (error, bool) { return err, true } fmt.Sscanf(event.body, "%s %s %s %s", &channelName, &rGesture, &lGesture, &target) + if target == "" { + response.Type = "dm" + response.Message = "missing target" + event.ResponseChannel <- response + return fmt.Errorf("missing target for waving hands"), true + } if channelName != "" { c, err := event.mm.GetChannelByName(channelName) if err != nil { @@ -248,7 +254,7 @@ func handleGameWithDirective(event BotGame, err error) (error, bool) { } g := Game{gData: wHGameData, Channel: channel} - p, err := GetCurrentPlayer(g, name) + p, err := GetCurrentPlayer(&g, name) if err != nil { return err, true @@ -277,11 +283,16 @@ func handleGameWithDirective(event BotGame, err error) (error, bool) { // Check All Players for gestures hasAllMoves := CheckAllPlayers(g) if hasAllMoves { - for i, p := range g.gData.Players { + for i := range g.gData.Players { + p := g.gData.Players[i] rG := p.Right.GetAt(len(p.Right.Sequence) - 1) lG := p.Left.GetAt(len(p.Left.Sequence) - 1) - if p.Target != "" { - t, err = FindTarget(g, p.Target) + if p.GetTarget() != "" { + t, err = FindTarget(g, p.GetTarget()) + if err != nil { + return err, true + } + t.Selector = p.GetTarget() } announceGestures(&p, event.ResponseChannel, response, string(rG), string(lG), p.GetTarget()) sr, err := spells.GetSurrenderSpell(wavinghands.GetSpell("Surrender")) @@ -480,7 +491,7 @@ func FindTarget(g Game, selector string) (*wavinghands.Living, error) { return &wavinghands.Living{}, fmt.Errorf("not found") } -func GetCurrentPlayer(g Game, name string) (*wavinghands.Wizard, error) { +func GetCurrentPlayer(g *Game, name string) (*wavinghands.Wizard, error) { for i, w := range g.gData.Players { if w.Name == name { return &g.gData.Players[i], nil diff --git a/internal/users/users.go b/internal/users/users.go index aaa3ec0..ba30ccd 100644 --- a/internal/users/users.go +++ b/internal/users/users.go @@ -44,14 +44,16 @@ func SetupUsers(mm *mmclient.MMClient, c cache.Cache) error { func HandlePost(post *model.Post, mm *mmclient.MMClient, c cache.Cache) error { user, _, err := mm.Client.GetUser(post.UserId, "") - key := KeyPrefix + user.Username - persisted, ok, _ := GetUser(user.Username, c) + if err == nil { + key := KeyPrefix + user.Username + persisted, ok, _ := GetUser(user.Username, c) - if ok { - persisted.Message = post.Message + if ok { + persisted.Message = post.Message - ub, _ := json.Marshal(persisted) - c.Put(key, ub) + ub, _ := json.Marshal(persisted) + c.Put(key, ub) + } } return err From 03e9753524fee8a80895d9199ae6cb251f168a1f Mon Sep 17 00:00:00 2001 From: Benjamin Payne Date: Tue, 22 Nov 2022 16:03:35 -0700 Subject: [PATCH 05/12] Fixes cross channel communications which were broken by implementation of channels to do multi-communications. --- internal/handler/command-handler.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/internal/handler/command-handler.go b/internal/handler/command-handler.go index 97d7fb2..21b5b2a 100644 --- a/internal/handler/command-handler.go +++ b/internal/handler/command-handler.go @@ -15,7 +15,9 @@ func (h *Handler) HandleCommand(quit chan bool, event *model.WebSocketEvent) err bc, err := cmds.NewBotCommand(post.Message, sender) bc.ResponseChannel = h.ResponseChannel - bc.ReplyChannel, _, err = h.Mm.Client.GetChannel(channelId, "") + if bc.ReplyChannel == nil { + bc.ReplyChannel, _, err = h.Mm.Client.GetChannel(channelId, "") + } bc.Quit = quit if err != nil { return h.SendErrorResponse(post, err.Error()) From 80d79b0f2a7e960da047d2cd3c83a657ff260c4a Mon Sep 17 00:00:00 2001 From: Benjamin Payne Date: Thu, 1 Dec 2022 08:29:48 -0700 Subject: [PATCH 06/12] Fixes an issue where botCommand's channel is not null, but it is empty. --- internal/comms/comms.go | 9 +++++---- internal/handler/command-handler.go | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/internal/comms/comms.go b/internal/comms/comms.go index f222cec..d19eaf7 100644 --- a/internal/comms/comms.go +++ b/internal/comms/comms.go @@ -34,10 +34,11 @@ func (h *MessageHandler) StartMessageHandler() { } func (h *MessageHandler) SendMessage(r *Response) { - post := &model.Post{} - post.ChannelId = r.ReplyChannelId - post.Message = r.Message - post.UserId = r.UserId + post := &model.Post{ + ChannelId: r.ReplyChannelId, + Message: r.Message, + UserId: r.UserId, + } var err error checkMsg := strings.Split(r.Message, " ") if r.Type == "command" { diff --git a/internal/handler/command-handler.go b/internal/handler/command-handler.go index 21b5b2a..7ff451a 100644 --- a/internal/handler/command-handler.go +++ b/internal/handler/command-handler.go @@ -15,7 +15,7 @@ func (h *Handler) HandleCommand(quit chan bool, event *model.WebSocketEvent) err bc, err := cmds.NewBotCommand(post.Message, sender) bc.ResponseChannel = h.ResponseChannel - if bc.ReplyChannel == nil { + if bc.ReplyChannel == nil || bc.ReplyChannel.Id == "" { bc.ReplyChannel, _, err = h.Mm.Client.GetChannel(channelId, "") } bc.Quit = quit From d3a69a0817caf4dd3537fe5d00d78fef3fa0362c Mon Sep 17 00:00:00 2001 From: Benjamin Payne Date: Wed, 11 Jan 2023 20:58:16 -0700 Subject: [PATCH 07/12] Move web socket to config --- internal/mmclient/mmclient.go | 11 ++++++----- internal/settings/config.go | 9 +++++---- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/internal/mmclient/mmclient.go b/internal/mmclient/mmclient.go index 63107f5..3872128 100644 --- a/internal/mmclient/mmclient.go +++ b/internal/mmclient/mmclient.go @@ -24,10 +24,11 @@ type MMClient struct { } type Server struct { - HOST string `yaml:"host"` - PROTOCOL string `yaml:"protocol"` - PORT string `yaml:"port"` - CACHE_URI string `yaml:"cache_uri"` + HOST string `yaml:"host"` + PROTOCOL string `yaml:"protocol"` + PORT string `yaml:"port"` + CACHE_URI string `yaml:"cache_uri"` + WS_PROTOCOL string `yaml:"ws_protocol"` } // Documentation for the Go driver can be found @@ -240,7 +241,7 @@ func (c *MMClient) SendMsgToChannel(msg string, channelId string, prePost *model func (c *MMClient) NewWebSocketClient() (*model.WebSocketClient, error) { var err error - uri := fmt.Sprintf("wss://%s:%s", c.Server.HOST, c.Server.PORT) + uri := fmt.Sprintf("%s://%s:%s", c.Server.WS_PROTOCOL, c.Server.HOST, c.Server.PORT) ws, appErr := model.NewWebSocketClient4(uri, c.Client.AuthToken) if appErr != nil { diff --git a/internal/settings/config.go b/internal/settings/config.go index 6b829d3..ad45a6c 100644 --- a/internal/settings/config.go +++ b/internal/settings/config.go @@ -8,10 +8,11 @@ import ( type Config struct { Server struct { - HOST string `yaml:"host"` - PROTOCOL string `yaml:"protocol"` - PORT string `yaml:"port"` - CACHE_URI string `yaml:"cache_uri"` + HOST string `yaml:"host"` + PROTOCOL string `yaml:"protocol"` + PORT string `yaml:"port"` + CACHE_URI string `yaml:"cache_uri"` + WS_PROTOCOL string `yaml:"ws_protocol"` } `yaml:"server"` Bot struct { SAMPLE_NAME string `yaml:"sample_name"` From 9519979dddda1ba1813b80c49f6912d302dd1972 Mon Sep 17 00:00:00 2001 From: Benjamin Payne Date: Wed, 11 Jan 2023 20:59:43 -0700 Subject: [PATCH 08/12] Fixed timing of waving-hands --- internal/handler/games/wh.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/internal/handler/games/wh.go b/internal/handler/games/wh.go index b0dd8e8..c7d5564 100644 --- a/internal/handler/games/wh.go +++ b/internal/handler/games/wh.go @@ -12,6 +12,7 @@ import ( "golang.org/x/exp/slices" "reflect" "strings" + "time" ) type ( @@ -302,6 +303,7 @@ func handleGameWithDirective(event BotGame, err error) (error, bool) { surrenderString, err := sr.Cast(&g.gData.Players[i], t) if err == nil && surrenderString != "" { response.Message = surrenderString + time.Sleep(time.Second) event.ResponseChannel <- response } else if err != nil { return err, true @@ -353,7 +355,8 @@ func handleGameWithDirective(event BotGame, err error) (error, bool) { winner, err := getWHWinner(g) if err == nil { - response.Message = fmt.Sprintf("/echo %s \"has won the game of waving hands.\" 2", winner.Name) + time.Sleep(time.Second) + response.Message = fmt.Sprintf("%s has won the game of waving hands.", winner.Name) event.ResponseChannel <- response ClearGame(g.Channel.Id, event.Cache) @@ -473,7 +476,7 @@ func FindTarget(g Game, selector string) (*wavinghands.Living, error) { continue } - if monster == "" { + if wizard != nil && monster == "" { wizard.Living.Selector = selector return &wizard.Living, nil } From e3fed2edc265b5527ec7c404920af4def67cbc95 Mon Sep 17 00:00:00 2001 From: Benjamin Payne Date: Tue, 31 Jan 2023 21:51:18 -0700 Subject: [PATCH 09/12] =?UTF-8?q?=F0=9F=90=9B=20Fixes=20panic=20in=20help?= =?UTF-8?q?=20without=20providing=20a=20spell.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/handler/games/wavinghands/wavinghands.go | 4 ++-- internal/handler/games/wh.go | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/internal/handler/games/wavinghands/wavinghands.go b/internal/handler/games/wavinghands/wavinghands.go index 621de21..0af6362 100644 --- a/internal/handler/games/wavinghands/wavinghands.go +++ b/internal/handler/games/wavinghands/wavinghands.go @@ -107,9 +107,9 @@ func GetHelpSpell(chSp string) string { var response string if spell.Name == "" { - response = fmt.Sprintf("/echo %s wasn't a spell.\n", chSp) + response = fmt.Sprintf("%s wasn't a spell.\n", chSp) } else { - response = fmt.Sprintf("/echo %s is defined as follows:\n```\n", spell.Name) + response = fmt.Sprintf("%s is defined as follows:\n```\n", spell.Name) response += fmt.Sprintf("Description: %s\n", spell.Description) response += fmt.Sprintf("Usage: %s\n", spell.Usage) response += "```\n" diff --git a/internal/handler/games/wh.go b/internal/handler/games/wh.go index c7d5564..e1ce9a8 100644 --- a/internal/handler/games/wh.go +++ b/internal/handler/games/wh.go @@ -190,7 +190,11 @@ func handleGameWithDirective(event BotGame, err error) (error, bool) { directive := parts[0] switch directive { case "help": - response.Message = wavinghands.GetHelpSpell(parts[1]) + if len(parts) > 1 { + response.Message = wavinghands.GetHelpSpell(parts[1]) + } else { + response.Message = "What spell would you like help with?" + } response.Type = "dm" event.ResponseChannel <- response return nil, true From b8a5d050f5ad3cd24b9b801da3e8d1c927c0e274 Mon Sep 17 00:00:00 2001 From: Benjamin Payne Date: Thu, 2 Feb 2023 21:10:00 -0700 Subject: [PATCH 10/12] =?UTF-8?q?=E2=9C=A8=20Added=20the=20stab=20gesture.?= =?UTF-8?q?=20\?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This gesture does not interrupt a sequence. --- .../handler/games/wavinghands/spells/stab.go | 63 +++++++++++++++++++ internal/handler/games/wh.go | 13 +++- internal/handler/games/wh_test.go | 2 +- 3 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 internal/handler/games/wavinghands/spells/stab.go diff --git a/internal/handler/games/wavinghands/spells/stab.go b/internal/handler/games/wavinghands/spells/stab.go new file mode 100644 index 0000000..112d4dd --- /dev/null +++ b/internal/handler/games/wavinghands/spells/stab.go @@ -0,0 +1,63 @@ +package spells + +import ( + "fmt" + "github.com/pyrousnet/pyrous-gobot/internal/handler/games/wavinghands" + "strings" +) + +type Stab struct { + Name string `json:"name"` + Sequence string `json:"sequence"` + ShSequence string `json:"sh-sequence"` + Description string `json:"description"` + Usage string `json:"usage"` + Damage int `json:"damage"` + Resistences string `json:"resistences"` + Protections string `json:"protections"` +} + +func (s Stab) Cast(wizard *wavinghands.Wizard, target *wavinghands.Living) (string, error) { + var returnString string = "" + if strings.HasSuffix(wizard.Right.Sequence, "1") { + wizard.Right.Set(strings.TrimRight(wizard.Right.Sequence, "1")) + + if strings.Contains(target.Wards, "shield") { + returnString += fmt.Sprintf("%s tries to stab %s with right hand but they were protected by a shield and took no damage", wizard.Name, target.Selector) + } else { + target.HitPoints -= s.Damage + returnString += fmt.Sprintf("%s stabbed %s with right hand", wizard.Name, target.Selector) + } + } + if strings.HasSuffix(wizard.Left.Sequence, "1") { + wizard.Left.Set(strings.TrimRight(wizard.Left.Sequence, "1")) + if returnString != "" { + returnString += "\n" + } + if strings.Contains(target.Wards, "shield") { + returnString += fmt.Sprintf("%s tries to stab %s with left hand but they were protected by a shield and took no damage", wizard.Name, target.Selector) + } else { + target.HitPoints -= s.Damage + returnString += fmt.Sprintf("%s stabbed %s with left hand", wizard.Name, target.Selector) + } + } + + return returnString, nil +} + +func GetStabSpell(s *wavinghands.Spell, e error) (*Stab, error) { + if e != nil { + return &Stab{}, e + } + + return &Stab{ + Name: s.Name, + Sequence: s.Sequence, + ShSequence: s.ShSequence, + Description: s.Description, + Usage: s.Usage, + Damage: s.Damage, + Resistences: s.Resistances, + Protections: s.Protections, + }, nil +} diff --git a/internal/handler/games/wh.go b/internal/handler/games/wh.go index e1ce9a8..28b06f6 100644 --- a/internal/handler/games/wh.go +++ b/internal/handler/games/wh.go @@ -273,7 +273,7 @@ func handleGameWithDirective(event BotGame, err error) (error, bool) { if rGesture == "nothing" { rGesture = "0" } - if rGesture == "stab" { + if rGesture == "nothing" { lGesture = "0" } rightGestures := append(p.Right.Get(), rGesture[0]) @@ -338,6 +338,17 @@ func handleGameWithDirective(event BotGame, err error) (error, bool) { } else if err != nil { return err, true } + s, sErr := spells.GetStabSpell(wavinghands.GetSpell("Stab")) + if sErr != nil { + return sErr, true + } + sResult, err := s.Cast(&g.gData.Players[i], t) + if err == nil && sResult != "" { + response.Message = sResult + event.ResponseChannel <- response + } else if err != nil { + return err, true + } CHW, err := spells.GetCauseHeavyWoundsSpell(wavinghands.GetSpell("Cause Heavy Wounds")) if err != nil { return err, true diff --git a/internal/handler/games/wh_test.go b/internal/handler/games/wh_test.go index 07c6bf1..b14ecb8 100644 --- a/internal/handler/games/wh_test.go +++ b/internal/handler/games/wh_test.go @@ -77,7 +77,7 @@ func Test_handleEmptyBody(t *testing.T) { go func() { got, got1 := handleEmptyBody(tt.args.event) if got != tt.want { - t.Errorf("handleEmptyBody() got = %v, want %v", got1, tt.want1) + t.Errorf("handleEmptyBody() got = %v, want %v", got, tt.want1) } if got1 != tt.want1 { From 9deb76d4d6f36e8fd05e7737420984a6149b4469 Mon Sep 17 00:00:00 2001 From: Benjamin Payne Date: Sat, 17 Jun 2023 15:30:06 -0600 Subject: [PATCH 11/12] =?UTF-8?q?[wavinghands]:=20=F0=9F=90=9B=20Fixe?= =?UTF-8?q?s=20issue=20with=20rounds=20not=20being=20counted?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rounds were not being counted properly because the game was not passed by reference. --- .../wavinghands/spells/cure-heavy-wounds.go | 6 + .../handler/games/wavinghands/wavinghands.go | 8 +- internal/handler/games/wh.go | 168 +++++++++--------- 3 files changed, 100 insertions(+), 82 deletions(-) diff --git a/internal/handler/games/wavinghands/spells/cure-heavy-wounds.go b/internal/handler/games/wavinghands/spells/cure-heavy-wounds.go index af362db..966ef27 100644 --- a/internal/handler/games/wavinghands/spells/cure-heavy-wounds.go +++ b/internal/handler/games/wavinghands/spells/cure-heavy-wounds.go @@ -7,6 +7,8 @@ import ( "strings" ) +const HealingPoints = 2 + type CureHeavyWounds struct { Name string `json:"name"` Sequence string `json:"sequence"` @@ -35,6 +37,10 @@ func (cHW CureHeavyWounds) Cast(wizard *wavinghands.Wizard, target *wavinghands. wards = append(wards, "cureHeavyWounds") // Lasts one round target.Wards = strings.Join(wards, ",") + target.HitPoints += HealingPoints + if target.HitPoints > wavinghands.MaxWhHp { + target.HitPoints = wavinghands.MaxWhHp + } returnString += fmt.Sprintf("%s has cast Cure Heavy Wounds on %s", wizard.Name, target.Selector) } diff --git a/internal/handler/games/wavinghands/wavinghands.go b/internal/handler/games/wavinghands/wavinghands.go index 0af6362..3015417 100644 --- a/internal/handler/games/wavinghands/wavinghands.go +++ b/internal/handler/games/wavinghands/wavinghands.go @@ -12,6 +12,7 @@ const ( minTeams = 2 maxTeams = 6 PREFIX = "wh-" + MaxWhHp = 15 ) type ( @@ -62,11 +63,14 @@ func (h *Hand) Set(s string) { h.Sequence = s } -func (h Hand) Get() []byte { +func (h *Hand) Get() []byte { return []byte(h.Sequence) } -func (h Hand) GetAt(index int) byte { +func (h *Hand) GetAt(index int) byte { + if index < 0 { + return ' ' + } return h.Sequence[index] } diff --git a/internal/handler/games/wh.go b/internal/handler/games/wh.go index 28b06f6..2755038 100644 --- a/internal/handler/games/wh.go +++ b/internal/handler/games/wh.go @@ -41,7 +41,7 @@ func NewWavingHands(event BotGame) (Game, error) { Left: wavinghands.Hand{}, Name: name, Living: wavinghands.Living{ - HitPoints: 15, + HitPoints: wavinghands.MaxWhHp, }, Curses: "", Protections: "", @@ -63,7 +63,7 @@ func NewWavingHands(event BotGame) (Game, error) { Left: wavinghands.Hand{}, Name: name, Living: wavinghands.Living{ - HitPoints: 15, + HitPoints: wavinghands.MaxWhHp, }, Curses: "", Protections: "", @@ -288,84 +288,10 @@ func handleGameWithDirective(event BotGame, err error) (error, bool) { // Check All Players for gestures hasAllMoves := CheckAllPlayers(g) if hasAllMoves { - for i := range g.gData.Players { - p := g.gData.Players[i] - rG := p.Right.GetAt(len(p.Right.Sequence) - 1) - lG := p.Left.GetAt(len(p.Left.Sequence) - 1) - if p.GetTarget() != "" { - t, err = FindTarget(g, p.GetTarget()) - if err != nil { - return err, true - } - t.Selector = p.GetTarget() - } - announceGestures(&p, event.ResponseChannel, response, string(rG), string(lG), p.GetTarget()) - sr, err := spells.GetSurrenderSpell(wavinghands.GetSpell("Surrender")) - if err != nil { - return err, true - } - surrenderString, err := sr.Cast(&g.gData.Players[i], t) - if err == nil && surrenderString != "" { - response.Message = surrenderString - time.Sleep(time.Second) - event.ResponseChannel <- response - } else if err != nil { - return err, true - } - // Run Protection Spells - - cHW, err := spells.GetCureHeavyWoundsSpell(wavinghands.GetSpell("Cure Heavy Wounds")) - if err != nil { - return err, true - } - chwResult, err := cHW.Cast(&g.gData.Players[i], t) - if err == nil && chwResult != "" { - response.Message = chwResult - event.ResponseChannel <- response - } else if err != nil { - return err, true - } - - // Run Damage Spells - m, mErr := spells.GetMissileSpell(wavinghands.GetSpell("Missile")) - if mErr != nil { - return mErr, true - } - mResult, err := m.Cast(&g.gData.Players[i], t) - if err == nil && mResult != "" { - response.Message = mResult - event.ResponseChannel <- response - } else if err != nil { - return err, true - } - s, sErr := spells.GetStabSpell(wavinghands.GetSpell("Stab")) - if sErr != nil { - return sErr, true - } - sResult, err := s.Cast(&g.gData.Players[i], t) - if err == nil && sResult != "" { - response.Message = sResult - event.ResponseChannel <- response - } else if err != nil { - return err, true - } - CHW, err := spells.GetCauseHeavyWoundsSpell(wavinghands.GetSpell("Cause Heavy Wounds")) - if err != nil { - return err, true - } - chwResult, err = CHW.Cast(&g.gData.Players[i], t) - if err == nil && chwResult != "" { - response.Message = chwResult - event.ResponseChannel <- response - } else if err != nil { - return err, true - } - - cHW.Clear(&p.Living) + err, b, done := executeRound(event, &g, t, err, response) + if done { + return err, b } - - // Run Summon Spells - g.gData.Round += 1 } winner, err := getWHWinner(g) @@ -382,6 +308,88 @@ func handleGameWithDirective(event BotGame, err error) (error, bool) { return nil, true } +func executeRound(event BotGame, g *Game, t *wavinghands.Living, err error, response comms.Response) (error, bool, bool) { + for i := range g.gData.Players { + p := g.gData.Players[i] + rG := p.Right.GetAt(len(p.Right.Sequence) - 1) + lG := p.Left.GetAt(len(p.Left.Sequence) - 1) + if p.GetTarget() != "" { + t, err = FindTarget(g, p.GetTarget()) + if err != nil { + return err, true, true + } + t.Selector = p.GetTarget() + } + announceGestures(&p, event.ResponseChannel, response, string(rG), string(lG), p.GetTarget()) + sr, err := spells.GetSurrenderSpell(wavinghands.GetSpell("Surrender")) + if err != nil { + return err, true, true + } + surrenderString, err := sr.Cast(&g.gData.Players[i], t) + if err == nil && surrenderString != "" { + response.Message = surrenderString + time.Sleep(time.Second) + event.ResponseChannel <- response + } else if err != nil { + return err, true, true + } + // Run Protection Spells + + cHW, err := spells.GetCureHeavyWoundsSpell(wavinghands.GetSpell("Cure Heavy Wounds")) + if err != nil { + return err, true, true + } + chwResult, err := cHW.Cast(&g.gData.Players[i], t) + if err == nil && chwResult != "" { + response.Message = chwResult + event.ResponseChannel <- response + } else if err != nil { + return err, true, true + } + + // Run Damage Spells + m, mErr := spells.GetMissileSpell(wavinghands.GetSpell("Missile")) + if mErr != nil { + return mErr, true, true + } + mResult, err := m.Cast(&g.gData.Players[i], t) + if err == nil && mResult != "" { + response.Message = mResult + event.ResponseChannel <- response + } else if err != nil { + return err, true, true + } + s, sErr := spells.GetStabSpell(wavinghands.GetSpell("Stab")) + if sErr != nil { + return sErr, true, true + } + sResult, err := s.Cast(&g.gData.Players[i], t) + if err == nil && sResult != "" { + response.Message = sResult + event.ResponseChannel <- response + } else if err != nil { + return err, true, true + } + CHW, err := spells.GetCauseHeavyWoundsSpell(wavinghands.GetSpell("Cause Heavy Wounds")) + if err != nil { + return err, true, true + } + chwResult, err = CHW.Cast(&g.gData.Players[i], t) + if err == nil && chwResult != "" { + response.Message = chwResult + event.ResponseChannel <- response + } else if err != nil { + return err, true, true + } + + cHW.Clear(&p.Living) + } + + // Run Summon Spells + g.gData.Round += 1 + return err, false, false +} + func announceGestures( p *wavinghands.Wizard, channel chan comms.Response, @@ -474,7 +482,7 @@ func getWHWinner(g Game) (wavinghands.Wizard, error) { } } -func FindTarget(g Game, selector string) (*wavinghands.Living, error) { +func FindTarget(g *Game, selector string) (*wavinghands.Living, error) { var name, monster string var wizard *wavinghands.Wizard parts := strings.Split(selector, ":") From e1a46f86a75fd511f7fa4173d5417d6f893cc75b Mon Sep 17 00:00:00 2001 From: Benjamin Payne Date: Sat, 1 Jul 2023 18:08:12 -0600 Subject: [PATCH 12/12] =?UTF-8?q?=E2=9C=A8=20=20Adds=20shield=20spell?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Includes a new spell to shield from damage causing spells like missile and non-spells like stab. --- .../wavinghands/spells/cause-heavy-wounds.go | 6 +- .../wavinghands/spells/cure-heavy-wounds.go | 6 +- .../games/wavinghands/spells/missile.go | 6 +- .../games/wavinghands/spells/shield.go | 77 +++++++++++++++++++ .../handler/games/wavinghands/spells/stab.go | 6 +- .../games/wavinghands/spells/surrender.go | 6 +- .../handler/games/wavinghands/wavinghands.go | 2 +- internal/handler/games/wh.go | 12 +++ spells.json | 2 +- 9 files changed, 106 insertions(+), 17 deletions(-) create mode 100644 internal/handler/games/wavinghands/spells/shield.go diff --git a/internal/handler/games/wavinghands/spells/cause-heavy-wounds.go b/internal/handler/games/wavinghands/spells/cause-heavy-wounds.go index 464337d..11def61 100644 --- a/internal/handler/games/wavinghands/spells/cause-heavy-wounds.go +++ b/internal/handler/games/wavinghands/spells/cause-heavy-wounds.go @@ -13,11 +13,11 @@ type CauseHeavyWounds struct { Description string `json:"description"` Usage string `json:"usage"` Damage int `json:"damage"` - Resistences string `json:"resistences"` + Resistances string `json:"resistances"` Protections string `json:"protections"` } -func (cHW CauseHeavyWounds) Cast(wizard *wavinghands.Wizard, target *wavinghands.Living) (string, error) { +func (cHW *CauseHeavyWounds) Cast(wizard *wavinghands.Wizard, target *wavinghands.Living) (string, error) { var returnString string = "" if strings.HasSuffix(wizard.Right.Sequence, cHW.Sequence) { @@ -56,7 +56,7 @@ func GetCauseHeavyWoundsSpell(s *wavinghands.Spell, e error) (*CauseHeavyWounds, Description: s.Description, Usage: s.Usage, Damage: s.Damage, - Resistences: s.Resistances, + Resistances: s.Resistances, Protections: s.Protections, }, nil } diff --git a/internal/handler/games/wavinghands/spells/cure-heavy-wounds.go b/internal/handler/games/wavinghands/spells/cure-heavy-wounds.go index 966ef27..7fa1de9 100644 --- a/internal/handler/games/wavinghands/spells/cure-heavy-wounds.go +++ b/internal/handler/games/wavinghands/spells/cure-heavy-wounds.go @@ -16,11 +16,11 @@ type CureHeavyWounds struct { Description string `json:"description"` Usage string `json:"usage"` Damage int `json:"damage"` - Resistences string `json:"resistences"` + Resistances string `json:"resistances"` Protections string `json:"protections"` } -func (cHW CureHeavyWounds) Cast(wizard *wavinghands.Wizard, target *wavinghands.Living) (string, error) { +func (cHW *CureHeavyWounds) Cast(wizard *wavinghands.Wizard, target *wavinghands.Living) (string, error) { var returnString string = "" if strings.HasSuffix(wizard.Right.Sequence, cHW.Sequence) { wards := strings.Split(target.Wards, ",") @@ -59,7 +59,7 @@ func GetCureHeavyWoundsSpell(s *wavinghands.Spell, e error) (*CureHeavyWounds, e Description: s.Description, Usage: s.Usage, Damage: s.Damage, - Resistences: s.Resistances, + Resistances: s.Resistances, Protections: s.Protections, }, nil } diff --git a/internal/handler/games/wavinghands/spells/missile.go b/internal/handler/games/wavinghands/spells/missile.go index 9268a15..8f88af0 100644 --- a/internal/handler/games/wavinghands/spells/missile.go +++ b/internal/handler/games/wavinghands/spells/missile.go @@ -13,11 +13,11 @@ type Missile struct { Description string `json:"description"` Usage string `json:"usage"` Damage int `json:"damage"` - Resistences string `json:"resistences"` + Resistances string `json:"resistances"` Protections string `json:"protections"` } -func (m Missile) Cast(wizard *wavinghands.Wizard, target *wavinghands.Living) (string, error) { +func (m *Missile) Cast(wizard *wavinghands.Wizard, target *wavinghands.Living) (string, error) { var returnString string = "" if strings.HasSuffix(wizard.Right.Sequence, m.Sequence) { @@ -55,7 +55,7 @@ func GetMissileSpell(s *wavinghands.Spell, e error) (*Missile, error) { Description: s.Description, Usage: s.Usage, Damage: s.Damage, - Resistences: s.Resistances, + Resistances: s.Resistances, Protections: s.Protections, }, nil } diff --git a/internal/handler/games/wavinghands/spells/shield.go b/internal/handler/games/wavinghands/spells/shield.go new file mode 100644 index 0000000..26e2bab --- /dev/null +++ b/internal/handler/games/wavinghands/spells/shield.go @@ -0,0 +1,77 @@ +package spells + +import ( + "fmt" + "github.com/pyrousnet/pyrous-gobot/internal/handler/games/wavinghands" + "golang.org/x/exp/slices" + "strings" +) + +type Shield struct { + Name string `json:"name"` + Sequence string `json:"sequence"` + ShSequence string `json:"sh-sequence"` + Description string `json:"description"` + Usage string `json:"usage"` + Damage int `json:"damage"` + Resistances string `json:"resistances"` + Protections string `json:"protections"` +} + +func (s *Shield) Cast(wizard *wavinghands.Wizard, target *wavinghands.Living) (string, error) { + var returnString string + if strings.HasSuffix(wizard.Right.Sequence, s.Sequence) || strings.HasSuffix(wizard.Left.Sequence, s.Sequence) { + wards := strings.Split(target.Wards, ",") + wards = append(wards, "shield") + target.Wards = strings.Join(wards, ",") + + returnString = fmt.Sprintf("%s has cast Shield on %s", wizard.Name, target.Selector) + } + return returnString, nil +} + +func GetShieldSpell(s *wavinghands.Spell, e error) (*Shield, error) { + if e != nil { + return &Shield{}, e + } + + return &Shield{ + Name: s.Name, + Sequence: s.Sequence, + ShSequence: s.ShSequence, + Description: s.Description, + Usage: s.Usage, + Damage: s.Damage, + Resistances: s.Resistances, + Protections: s.Protections, + }, nil +} + +func (s *Shield) Clear(target *wavinghands.Living) error { + if target.Wards == "" { + return nil + } + wards := strings.Split(target.Wards, ",") + idx := slices.Index(wards, "shield") + if idx >= 0 { + wards = wavinghands.Remove(wards, idx) + } + wards = removeEmptyValues(wards) + if len(wards) > 0 { + target.Wards = strings.Join(wards, ",") + } else { + target.Wards = "" + } + return nil +} + +func removeEmptyValues(items []string) []string { + var result []string + for _, str := range items { + if str != "" { + result = append(result, str) + } + } + + return result +} diff --git a/internal/handler/games/wavinghands/spells/stab.go b/internal/handler/games/wavinghands/spells/stab.go index 112d4dd..1c83467 100644 --- a/internal/handler/games/wavinghands/spells/stab.go +++ b/internal/handler/games/wavinghands/spells/stab.go @@ -13,11 +13,11 @@ type Stab struct { Description string `json:"description"` Usage string `json:"usage"` Damage int `json:"damage"` - Resistences string `json:"resistences"` + Resistances string `json:"resistances"` Protections string `json:"protections"` } -func (s Stab) Cast(wizard *wavinghands.Wizard, target *wavinghands.Living) (string, error) { +func (s *Stab) Cast(wizard *wavinghands.Wizard, target *wavinghands.Living) (string, error) { var returnString string = "" if strings.HasSuffix(wizard.Right.Sequence, "1") { wizard.Right.Set(strings.TrimRight(wizard.Right.Sequence, "1")) @@ -57,7 +57,7 @@ func GetStabSpell(s *wavinghands.Spell, e error) (*Stab, error) { Description: s.Description, Usage: s.Usage, Damage: s.Damage, - Resistences: s.Resistances, + Resistances: s.Resistances, Protections: s.Protections, }, nil } diff --git a/internal/handler/games/wavinghands/spells/surrender.go b/internal/handler/games/wavinghands/spells/surrender.go index ffb0683..931e0f5 100644 --- a/internal/handler/games/wavinghands/spells/surrender.go +++ b/internal/handler/games/wavinghands/spells/surrender.go @@ -13,11 +13,11 @@ type Surrender struct { Description string `json:"description"` Usage string `json:"usage"` Damage int `json:"damage"` - Resistences string `json:"resistences"` + Resistances string `json:"resistances"` Protections string `json:"protections"` } -func (s Surrender) Cast(wizard *wavinghands.Wizard, target *wavinghands.Living) (string, error) { +func (s *Surrender) Cast(wizard *wavinghands.Wizard, target *wavinghands.Living) (string, error) { if strings.HasSuffix(wizard.Right.Sequence, s.Sequence) && strings.HasSuffix(wizard.Left.Sequence, s.ShSequence) { wizard.Living.HitPoints = 0 @@ -38,7 +38,7 @@ func GetSurrenderSpell(s *wavinghands.Spell, e error) (*Surrender, error) { Description: s.Description, Usage: s.Usage, Damage: s.Damage, - Resistences: s.Resistances, + Resistances: s.Resistances, Protections: s.Protections, }, nil } diff --git a/internal/handler/games/wavinghands/wavinghands.go b/internal/handler/games/wavinghands/wavinghands.go index 3015417..b005950 100644 --- a/internal/handler/games/wavinghands/wavinghands.go +++ b/internal/handler/games/wavinghands/wavinghands.go @@ -10,7 +10,7 @@ import ( const ( minTeams = 2 - maxTeams = 6 + maxTeams = 2 PREFIX = "wh-" MaxWhHp = 15 ) diff --git a/internal/handler/games/wh.go b/internal/handler/games/wh.go index 2755038..17957d1 100644 --- a/internal/handler/games/wh.go +++ b/internal/handler/games/wh.go @@ -334,6 +334,17 @@ func executeRound(event BotGame, g *Game, t *wavinghands.Living, err error, resp return err, true, true } // Run Protection Spells + shld, err := spells.GetShieldSpell(wavinghands.GetSpell("Shield")) + if err != nil { + return err, true, true + } + shldResult, err := shld.Cast(&g.gData.Players[i], t) + if err == nil && shldResult != "" { + response.Message = shldResult + event.ResponseChannel <- response + } else if err != nil { + return err, true, true + } cHW, err := spells.GetCureHeavyWoundsSpell(wavinghands.GetSpell("Cure Heavy Wounds")) if err != nil { @@ -383,6 +394,7 @@ func executeRound(event BotGame, g *Game, t *wavinghands.Living, err error, resp } cHW.Clear(&p.Living) + shld.Clear(t) } // Run Summon Spells diff --git a/spells.json b/spells.json index 19b668e..f549ba9 100644 --- a/spells.json +++ b/spells.json @@ -82,7 +82,7 @@ "sequence": "p", "sh-sequence": "", "description": "This spell protects the subject from monsters (that is, creatures created by a summoning spell), from missile spells and from stabs by wizards. The shield will block any number of such attacks but lasts for only one round. The shield protects the subject on the turn in which it was cast.", - "usage": "Counter-Spell can be cast with Gestures: \nProffered Palm (P)", + "usage": "Shield can be cast with Gestures: \nProffered Palm (P)", "damage": 0, "resistances": "", "protections": "shield"