mirror of
https://github.com/FloatTech/ZeroBot-Plugin.git
synced 2025-12-19 13:59:39 +08:00
161 lines
4.0 KiB
Go
161 lines
4.0 KiB
Go
// Package wordle 猜单词
|
|
package wordle
|
|
|
|
import (
|
|
"errors"
|
|
"image/color"
|
|
"math/rand"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/FloatTech/zbputils/binary"
|
|
"github.com/FloatTech/zbputils/control"
|
|
"github.com/FloatTech/zbputils/control/order"
|
|
"github.com/FloatTech/zbputils/ctxext"
|
|
"github.com/FloatTech/zbputils/file"
|
|
"github.com/FloatTech/zbputils/img/writer"
|
|
"github.com/fogleman/gg"
|
|
zero "github.com/wdvxdr1123/ZeroBot"
|
|
"github.com/wdvxdr1123/ZeroBot/message"
|
|
)
|
|
|
|
var (
|
|
errLengthNotEnough = errors.New("length not enough")
|
|
errUnknownWord = errors.New("unknown word")
|
|
errTimesRunOut = errors.New("times run out")
|
|
)
|
|
|
|
const (
|
|
match = iota
|
|
exist
|
|
notexist
|
|
undone
|
|
)
|
|
|
|
var colors = [...]color.RGBA{
|
|
{125, 166, 108, 255},
|
|
{199, 183, 96, 255},
|
|
{123, 123, 123, 255},
|
|
{219, 219, 219, 255},
|
|
}
|
|
|
|
var words []wordpack
|
|
|
|
func init() {
|
|
en := control.Register("wordle", order.AcquirePrio(), &control.Options{
|
|
DisableOnDefault: false,
|
|
Help: "猜单词\n" +
|
|
"- 开始猜单词",
|
|
PublicDataFolder: "Wordle",
|
|
})
|
|
go func() {
|
|
data, err := file.GetLazyData(en.DataFolder()+"words.bin", true, true)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
words = loadwords(data)
|
|
}()
|
|
en.OnFullMatch("猜单词").SetBlock(true).Limit(ctxext.LimitByUser).
|
|
Handle(func(ctx *zero.Ctx) {
|
|
game := newWordleGame()
|
|
_, img, _ := game("")
|
|
ctx.SendChain(message.Image("base64://"+binary.BytesToString(img)), message.Text("请发送单词"))
|
|
// 没有图片就索取
|
|
next := zero.NewFutureEvent("message", 999, false, zero.RegexRule(`^[A-Z]{5}$|^[a-z]{5}$`))
|
|
recv, cancel := next.Repeat()
|
|
var msg message.Message
|
|
defer func() {
|
|
cancel()
|
|
ctx.Send(msg)
|
|
}()
|
|
for {
|
|
select {
|
|
case <-time.After(time.Second * 120):
|
|
return
|
|
case e := <-recv:
|
|
win, img, err := game(e.Message.String())
|
|
msg = []message.MessageSegment{message.Image("base64://" + binary.BytesToString(img))}
|
|
switch err {
|
|
case nil:
|
|
if win {
|
|
msg = append(msg, message.Text("你赢了"))
|
|
return
|
|
}
|
|
case errLengthNotEnough:
|
|
msg = append(msg, message.Text("单词长度错误"))
|
|
case errUnknownWord:
|
|
msg = append(msg, message.Text("不存在这样的单词"))
|
|
case errTimesRunOut:
|
|
msg = append(msg, message.Text("你输了"))
|
|
return
|
|
}
|
|
ctx.Send(msg)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
func newWordleGame() func(string) (bool, []byte, error) {
|
|
onhandpack := words[rand.Intn(len(words))]
|
|
onhand := onhandpack.String()
|
|
record := make([]string, 0, len(onhand)+1)
|
|
return func(s string) (win bool, base64Image []byte, err error) {
|
|
if s != "" {
|
|
s = strings.ToLower(s)
|
|
sp := pack(s)
|
|
if onhandpack == sp {
|
|
win = true
|
|
} else {
|
|
if len(s) != len(onhand) {
|
|
err = errLengthNotEnough
|
|
return
|
|
}
|
|
i := 0
|
|
for ; i < len(words); i++ {
|
|
if words[i] == sp {
|
|
break
|
|
}
|
|
}
|
|
if i >= len(words) || words[i] != sp {
|
|
err = errUnknownWord
|
|
return
|
|
}
|
|
}
|
|
if len(record) >= cap(record) {
|
|
err = errTimesRunOut
|
|
return
|
|
}
|
|
record = append(record, s)
|
|
}
|
|
var side = 20
|
|
ctx := gg.NewContext((side+2)*5+26, (side+2)*6+26)
|
|
ctx.SetColor(color.RGBA{255, 255, 255, 255})
|
|
ctx.Clear()
|
|
for i := 0; i < len(onhand)+1; i++ {
|
|
for j := 0; j < len(onhand); j++ {
|
|
if len(record) > i {
|
|
ctx.DrawRectangle(float64(10+j*(side+4)), float64(10+i*(side+4)), float64(side), float64(side))
|
|
switch {
|
|
case record[i][j] == onhand[j]:
|
|
ctx.SetColor(colors[match])
|
|
case strings.IndexByte(onhand, record[i][j]) != -1:
|
|
ctx.SetColor(colors[exist])
|
|
default:
|
|
ctx.SetColor(colors[notexist])
|
|
}
|
|
ctx.Fill()
|
|
ctx.SetColor(color.RGBA{255, 255, 255, 255})
|
|
ctx.DrawString(strings.ToUpper(string(record[i][j])), float64(10+j*(side+4)+7), float64(10+i*(side+4)+15))
|
|
} else {
|
|
ctx.DrawRectangle(float64(10+j*(side+4)+1), float64(10+i*(side+4)+1), float64(side-2), float64(side-2))
|
|
ctx.SetLineWidth(1)
|
|
ctx.SetColor(colors[undone])
|
|
ctx.Stroke()
|
|
}
|
|
}
|
|
}
|
|
base64Image, err = writer.ToBase64(ctx.Image())
|
|
return
|
|
}
|
|
}
|