156 lines
6.1 KiB
Forth
156 lines
6.1 KiB
Forth
module Degenz.RockPaperScissors
|
|
|
|
open System.Threading.Tasks
|
|
open DSharpPlus
|
|
open DSharpPlus.Entities
|
|
open DSharpPlus.EventArgs
|
|
open DSharpPlus.SlashCommands
|
|
open Degenz.Messaging
|
|
|
|
type Move =
|
|
| Rock
|
|
| Paper
|
|
| Scissors
|
|
|
|
type RoundResult =
|
|
| P1Win
|
|
| P2Win
|
|
| Draw
|
|
|
|
let moveFromString = function
|
|
| "rock" -> Rock
|
|
| "paper" -> Paper
|
|
| "scissors" -> Scissors
|
|
| _ -> failwith "Unknown RPS move"
|
|
|
|
let getWinner p1m p2m =
|
|
match p1m , p2m with
|
|
| Rock , Paper -> P2Win
|
|
| Rock , Scissors -> P1Win
|
|
| Paper , Rock -> P1Win
|
|
| Paper , Scissors -> P2Win
|
|
| Scissors , Rock -> P2Win
|
|
| Scissors , Paper -> P1Win
|
|
| _ , _ -> Draw
|
|
|
|
let leftGif = function
|
|
| Rock -> "https://s10.gifyu.com/images/Sprite-0001614d8697f32165af.gif"
|
|
| Paper -> "https://s10.gifyu.com/images/Sprite-0001e7e8ac379d1c5112.gif"
|
|
| Scissors -> "https://s10.gifyu.com/images/Sprite-00012c83b50d768a2ed1.gif"
|
|
|
|
let rightGif = function
|
|
| Rock -> "https://s10.gifyu.com/images/Sprite-0001b4002047d9699732.gif"
|
|
| Paper -> "https://s10.gifyu.com/images/Sprite-00014072202347b8271e.gif"
|
|
| Scissors -> "https://s10.gifyu.com/images/Sprite-0001c8532b0538ed8706.gif"
|
|
|
|
let rpsEmbed disabled opponentMove opponent =
|
|
let buttonId move =
|
|
match opponentMove with
|
|
| Some m -> $"RPS-{move}-{opponent.DiscordId}-{opponent.Name}-True-{m}"
|
|
| None -> $"RPS-{move}-{opponent.DiscordId}-{opponent.Name}-False"
|
|
let buttons =
|
|
[ DiscordButtonComponent(ButtonStyle.Primary, buttonId "rock", "🪨 Rock", disabled)
|
|
DiscordButtonComponent(ButtonStyle.Primary, buttonId "paper", "📜 Paper", disabled)
|
|
DiscordButtonComponent(ButtonStyle.Primary, buttonId "scissors", "✂ Scissors", disabled) ]
|
|
|> Seq.cast<DiscordComponent>
|
|
|
|
let embed =
|
|
DiscordEmbedBuilder()
|
|
.WithTitle("Rock Paper Scissors")
|
|
.AddField("Opponent", opponent.Name)
|
|
.WithImageUrl("https://s10.gifyu.com/images/222e9b8f5459e5d3a7d.png")
|
|
( buttons , embed )
|
|
|
|
let matchResultsEmbed winner move1 move2 player1 player2 =
|
|
let firstEmbed =
|
|
DiscordEmbedBuilder()
|
|
.WithTitle($"{player1.Name}'s Move")
|
|
.WithImageUrl(leftGif move1)
|
|
let secondEmbed =
|
|
DiscordEmbedBuilder()
|
|
.WithTitle($"{player2.Name}'s Move")
|
|
.WithImageUrl(rightGif move2)
|
|
|
|
let description =
|
|
match winner with
|
|
| P1Win -> $"{player1.Name} wins with {move1}"
|
|
| P2Win -> $"{player2.Name} wins with {move2}"
|
|
| Draw -> $"Draw! Both players played {move1}"
|
|
let thirdEmbed =
|
|
DiscordEmbedBuilder()
|
|
.WithTitle($"Results")
|
|
.WithDescription(description)
|
|
|
|
[ firstEmbed ; secondEmbed ; thirdEmbed ]
|
|
|
|
let playRPS target ctx =
|
|
PlayerInteractions.executePlayerActionWithTarget target ctx (fun _ defender -> async {
|
|
let buttons , embed = rpsEmbed false None defender
|
|
let builder =
|
|
DiscordFollowupMessageBuilder()
|
|
.AddComponents(buttons)
|
|
.AddEmbed(embed)
|
|
.AsEphemeral(true)
|
|
do! ctx.FollowUp (builder) |> Async.AwaitTask
|
|
})
|
|
|
|
let handleRPS (ctx : IDiscordContext) =
|
|
let tokens = ctx.GetInteractionId().Split("-")
|
|
let move = tokens.[1]
|
|
let targetId = uint64 tokens.[2]
|
|
let isResponse = tokens.[4] = "True"
|
|
PlayerInteractions.executePlayerActionWithTargetId false targetId ctx (fun attacker defender -> async {
|
|
if isResponse then
|
|
let eventCtx = ctx.GetContext() :?> ComponentInteractionCreateEventArgs
|
|
let buttons , embed = rpsEmbed true None attacker
|
|
let builder =
|
|
DiscordInteractionResponseBuilder()
|
|
.AddComponents(buttons)
|
|
.AddEmbed(embed)
|
|
.AsEphemeral(true)
|
|
do! eventCtx.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage, builder) |> Async.AwaitTask
|
|
let move1 = moveFromString move
|
|
let move2 = moveFromString tokens.[5]
|
|
let winner = getWinner move1 move2
|
|
let embeds = matchResultsEmbed winner move1 move2 attacker defender |> Seq.map (fun e -> e.Build())
|
|
let builder = DiscordMessageBuilder().AddEmbeds(embeds)
|
|
do! ctx.GetChannel().SendMessageAsync(builder) |> Async.AwaitTask |> Async.Ignore
|
|
else
|
|
let eventCtx = ctx.GetContext() :?> ComponentInteractionCreateEventArgs
|
|
let buttons , embed = rpsEmbed true None attacker
|
|
let builder =
|
|
DiscordInteractionResponseBuilder()
|
|
.AddComponents(buttons)
|
|
.AddEmbed(embed)
|
|
.AsEphemeral(true)
|
|
do! eventCtx.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage, builder) |> Async.AwaitTask
|
|
// do! sendFollowUpMessage ctx $"Sent challenge to {defender.Name}, wait till they respond"
|
|
let buttons , embed = rpsEmbed false (Some move) attacker
|
|
let builder =
|
|
DiscordMessageBuilder()
|
|
.WithContent($"<@{defender.DiscordId}>, you have been challenged to a match of Rock, Paper, Scissors. Pick your move!")
|
|
.AddComponents(buttons)
|
|
.AddEmbed(embed)
|
|
|
|
do! ctx.GetChannel().SendMessageAsync(builder) |> Async.AwaitTask |> Async.Ignore
|
|
})
|
|
|
|
type RPSGame() =
|
|
inherit ApplicationCommandModule ()
|
|
|
|
let enforceChannel (ctx : IDiscordContext) (storeFn : IDiscordContext -> Task) =
|
|
match ctx.GetChannel().Id with
|
|
| id when id = GuildEnvironment.channelArmory -> storeFn ctx
|
|
| _ ->
|
|
task {
|
|
let msg = $"You must go to <#{GuildEnvironment.channelArmory}> channel to buy or sell weapons"
|
|
do! Messaging.sendSimpleResponse ctx msg
|
|
}
|
|
|
|
[<SlashCommand("rock-paper-scissors", "Steal some money from another player, but you might go to prison if caught")>]
|
|
member this.RPS (ctx : InteractionContext, [<Option("target", "Who do you want to play with?")>] target : DiscordUser) =
|
|
// enforceChannel (DiscordInteractionContext ctx) (steal target)
|
|
playRPS target (DiscordInteractionContext ctx)
|
|
|
|
|