package rpgORdie import ( "fmt" "strings" "github.com/velour/catbase/bot" "github.com/velour/catbase/bot/msg" ) const ( DUDE = ":lion_face:" BOULDER = ":full_moon:" HOLE = ":new_moon:" EMPTY = ":white_large_square:" OK = iota INVALID = iota WIN = iota ) type RPGPlugin struct { Bot bot.Bot listenFor map[string]*board } type board struct { state [][]string x, y int } func NewRandomBoard() *board { boardSize := 5 b := board{ state: make([][]string, boardSize), x: boardSize - 1, y: boardSize - 1, } for i := 0; i < boardSize; i++ { b.state[i] = make([]string, boardSize) for j := 0; j < boardSize; j++ { b.state[i][j] = ":white_large_square:" } } b.state[boardSize-1][boardSize-1] = DUDE b.state[boardSize/2][boardSize/2] = BOULDER b.state[0][0] = HOLE return &b } func (b *board) toMessageString() string { lines := make([]string, len(b.state)) for i := 0; i < len(b.state); i++ { lines[i] = strings.Join(b.state[i], "") } return strings.Join(lines, "\n") } func (b *board) checkAndMove(dx, dy int) int { newX := b.x + dx newY := b.y + dy if newX < 0 || newY < 0 || newX >= len(b.state) || newY >= len(b.state) { return INVALID } if b.state[newY][newX] == HOLE { return INVALID } win := false if b.state[newY][newX] == BOULDER { newBoulderX := newX + dx newBoulderY := newY + dy if newBoulderX < 0 || newBoulderY < 0 || newBoulderX >= len(b.state) || newBoulderY >= len(b.state) { return INVALID } if b.state[newBoulderY][newBoulderX] != HOLE { b.state[newBoulderY][newBoulderX] = BOULDER } else { win = true } } b.state[newY][newX] = DUDE b.state[b.y][b.x] = EMPTY b.x = newX b.y = newY if win { return WIN } return OK } func New(b bot.Bot) *RPGPlugin { return &RPGPlugin{ Bot: b, listenFor: map[string]*board{}, } } func (p *RPGPlugin) Message(message msg.Message) bool { if strings.ToLower(message.Body) == "start rpg" { b := NewRandomBoard() _, ts := p.Bot.Send(bot.Message, message.Channel, b.toMessageString()) p.listenFor[ts] = b p.Bot.Send(bot.Reply, message.Channel, "Over here.", ts) return true } return false } func (p *RPGPlugin) LoadData() { } func (p *RPGPlugin) Help(channel string, parts []string) { p.Bot.Send(bot.Message, channel, "Go find a walkthrough or something.") } func (p *RPGPlugin) Event(kind string, message msg.Message) bool { return false } func (p *RPGPlugin) BotMessage(message msg.Message) bool { return false } func (p *RPGPlugin) RegisterWeb() *string { return nil } func (p *RPGPlugin) ReplyMessage(message msg.Message, identifier string) bool { if strings.ToLower(message.User.Name) != strings.ToLower(p.Bot.Config().Get("Nick", "bot")) { if b, ok := p.listenFor[identifier]; ok { var res int if message.Body == "left" { res = b.checkAndMove(-1, 0) } else if message.Body == "right" { res = b.checkAndMove(1, 0) } else if message.Body == "up" { res = b.checkAndMove(0, -1) } else if message.Body == "down" { res = b.checkAndMove(0, 1) } else { return false } switch res { case OK: p.Bot.Send(bot.Edit, message.Channel, b.toMessageString(), identifier) case WIN: p.Bot.Send(bot.Edit, message.Channel, b.toMessageString(), identifier) p.Bot.Send(bot.Reply, message.Channel, "congratulations, you beat the easiest level imaginable.", identifier) case INVALID: p.Bot.Send(bot.Reply, message.Channel, fmt.Sprintf("you can't move %s", message.Body), identifier) } return true } } return false }