Rock Paper Scissors
This commit is contained in:
parent
537145dae6
commit
9f756540f1
@ -60,12 +60,13 @@ module Game =
|
|||||||
else do! Messaging.sendFollowUpMessage ctx "Your target is not connected to the network, they must join first by using the /redpill command"
|
else do! Messaging.sendFollowUpMessage ctx "Your target is not connected to the network, they must join first by using the /redpill command"
|
||||||
} |> Async.StartAsTask :> Task
|
} |> Async.StartAsTask :> Task
|
||||||
|
|
||||||
let executePlayerActionWithTargetId (targetId : uint64) (ctx : IDiscordContext) (dispatch : PlayerData -> PlayerData -> Async<unit>) =
|
let executePlayerActionWithTargetId defer (targetId : uint64) (ctx : IDiscordContext) (dispatch : PlayerData -> PlayerData -> Async<unit>) =
|
||||||
async {
|
async {
|
||||||
let builder = DiscordInteractionResponseBuilder()
|
let builder = DiscordInteractionResponseBuilder()
|
||||||
builder.IsEphemeral <- true
|
builder.IsEphemeral <- true
|
||||||
builder.Content <- "Content"
|
builder.Content <- "Content"
|
||||||
do! ctx.Respond InteractionResponseType.DeferredChannelMessageWithSource builder |> Async.AwaitTask
|
if defer then
|
||||||
|
do! ctx.Respond InteractionResponseType.DeferredChannelMessageWithSource builder |> Async.AwaitTask
|
||||||
let! players =
|
let! players =
|
||||||
[ tryFindPlayer (ctx.GetDiscordMember().Id)
|
[ tryFindPlayer (ctx.GetDiscordMember().Id)
|
||||||
tryFindPlayer targetId ]
|
tryFindPlayer targetId ]
|
||||||
|
@ -211,7 +211,7 @@ let handleButtonEvent (_ : DiscordClient) (event : ComponentInteractionCreateEve
|
|||||||
| id when id.StartsWith("Defend") -> handleDefense eventCtx
|
| id when id.StartsWith("Defend") -> handleDefense eventCtx
|
||||||
| id when id.StartsWith("Trainer") -> Trainer.handleButtonEvent eventCtx |> Async.StartAsTask :> Task
|
| id when id.StartsWith("Trainer") -> Trainer.handleButtonEvent eventCtx |> Async.StartAsTask :> Task
|
||||||
| id when id.StartsWith("Steal") -> Thief.handleSteal eventCtx
|
| id when id.StartsWith("Steal") -> Thief.handleSteal eventCtx
|
||||||
| id when id.StartsWith("Steal") -> RockPaperScissors.handleRPS eventCtx
|
| id when id.StartsWith("RPS") -> RockPaperScissors.handleRPS eventCtx
|
||||||
| _ ->
|
| _ ->
|
||||||
task {
|
task {
|
||||||
let builder = DiscordInteractionResponseBuilder()
|
let builder = DiscordInteractionResponseBuilder()
|
||||||
|
@ -4,45 +4,137 @@ open System
|
|||||||
open System.Threading.Tasks
|
open System.Threading.Tasks
|
||||||
open DSharpPlus
|
open DSharpPlus
|
||||||
open DSharpPlus.Entities
|
open DSharpPlus.Entities
|
||||||
|
open DSharpPlus.EventArgs
|
||||||
open DSharpPlus.SlashCommands
|
open DSharpPlus.SlashCommands
|
||||||
open Degenz.Messaging
|
open Degenz.Messaging
|
||||||
|
|
||||||
type Move =
|
type Move =
|
||||||
| Rock
|
| Rock
|
||||||
| Paper
|
| Paper
|
||||||
| Scissor
|
| Scissors
|
||||||
|
|
||||||
type RoundResult =
|
type RoundResult =
|
||||||
| P1Win
|
| P1Win
|
||||||
| P2Win
|
| P2Win
|
||||||
| Draw
|
| Draw
|
||||||
|
|
||||||
let player1Won p1m p2m =
|
let moveFromString = function
|
||||||
|
| "rock" -> Rock
|
||||||
|
| "paper" -> Paper
|
||||||
|
| "scissors" -> Scissors
|
||||||
|
| _ -> failwith "Unknown RPS move"
|
||||||
|
|
||||||
|
let getWinner p1m p2m =
|
||||||
match p1m , p2m with
|
match p1m , p2m with
|
||||||
| Rock , Paper -> P2Win
|
| Rock , Paper -> P2Win
|
||||||
| Rock , Scissor -> P1Win
|
| Rock , Scissors -> P1Win
|
||||||
| Paper , Rock -> P1Win
|
| Paper , Rock -> P1Win
|
||||||
| Paper , Scissor -> P2Win
|
| Paper , Scissors -> P2Win
|
||||||
| Scissor , Rock -> P2Win
|
| Scissors , Rock -> P2Win
|
||||||
| Scissor , Paper -> P1Win
|
| Scissors , Paper -> P1Win
|
||||||
| _ , _ -> Draw
|
| _ , _ -> 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 =
|
let playRPS target ctx =
|
||||||
Game.executePlayerActionWithTarget target ctx (fun attacker defender -> async {
|
Game.executePlayerActionWithTarget target ctx (fun _ defender -> async {
|
||||||
let buttons =
|
let buttons , embed = rpsEmbed false None defender
|
||||||
[ DiscordButtonComponent(ButtonStyle.Primary, $"RPS-rock-{defender.DiscordId}-{defender.Name}", "🪨 Rock")
|
let builder =
|
||||||
DiscordButtonComponent(ButtonStyle.Primary, $"RPS-paper", "📜 Paper")
|
DiscordFollowupMessageBuilder()
|
||||||
DiscordButtonComponent(ButtonStyle.Primary, $"RPS-scissors", "✂ Scissors") ]
|
.AddComponents(buttons)
|
||||||
|> Seq.cast<DiscordComponent>
|
.AddEmbed(embed)
|
||||||
|
.AsEphemeral(true)
|
||||||
let builder = DiscordFollowupMessageBuilder()
|
do! ctx.FollowUp (builder) |> Async.AwaitTask
|
||||||
builder.AddComponents(buttons) |> ignore
|
|
||||||
builder.IsEphemeral <- true
|
|
||||||
|
|
||||||
do! ctx.FollowUp builder |> Async.AwaitTask
|
|
||||||
})
|
})
|
||||||
|
|
||||||
let handleRPS ctx = async.Zero() |> Async.StartAsTask
|
let handleRPS (ctx : IDiscordContext) =
|
||||||
|
let split = ctx.GetInteractionId().Split("-")
|
||||||
|
let move = split.[1]
|
||||||
|
let targetId = uint64 split.[2]
|
||||||
|
let isResponse = split.[4] = "True"
|
||||||
|
Game.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 split.[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() =
|
type RPSGame() =
|
||||||
inherit ApplicationCommandModule ()
|
inherit ApplicationCommandModule ()
|
||||||
|
@ -171,7 +171,7 @@ let handleSteal (ctx : IDiscordContext) =
|
|||||||
}
|
}
|
||||||
if answer = "yes" then
|
if answer = "yes" then
|
||||||
let targetId = uint64 split.[2]
|
let targetId = uint64 split.[2]
|
||||||
Game.executePlayerActionWithTargetId targetId ctx (fun attacker defender -> async {
|
Game.executePlayerActionWithTargetId true targetId ctx (fun attacker defender -> async {
|
||||||
do! attacker
|
do! attacker
|
||||||
|> Player.removeExpiredActions false
|
|> Player.removeExpiredActions false
|
||||||
|> checkVictimStealingCooldown defender
|
|> checkVictimStealingCooldown defender
|
||||||
|
@ -129,6 +129,7 @@ module Messaging =
|
|||||||
abstract member GetGuild : unit -> DiscordGuild
|
abstract member GetGuild : unit -> DiscordGuild
|
||||||
abstract member GetInteractionId : unit -> string
|
abstract member GetInteractionId : unit -> string
|
||||||
abstract member GetChannel : unit -> DiscordChannel
|
abstract member GetChannel : unit -> DiscordChannel
|
||||||
|
abstract member GetContext : unit -> obj
|
||||||
|
|
||||||
type DiscordInteractionContext(ctx : InteractionContext) =
|
type DiscordInteractionContext(ctx : InteractionContext) =
|
||||||
interface IDiscordContext with
|
interface IDiscordContext with
|
||||||
@ -144,6 +145,7 @@ module Messaging =
|
|||||||
member this.GetGuild() = ctx.Guild
|
member this.GetGuild() = ctx.Guild
|
||||||
member this.GetInteractionId() = string ctx.InteractionId
|
member this.GetInteractionId() = string ctx.InteractionId
|
||||||
member this.GetChannel() = ctx.Channel
|
member this.GetChannel() = ctx.Channel
|
||||||
|
member this.GetContext() = ctx
|
||||||
|
|
||||||
type DiscordEventContext(ctx : ComponentInteractionCreateEventArgs) =
|
type DiscordEventContext(ctx : ComponentInteractionCreateEventArgs) =
|
||||||
interface IDiscordContext with
|
interface IDiscordContext with
|
||||||
@ -159,6 +161,7 @@ module Messaging =
|
|||||||
member this.GetGuild() = ctx.Guild
|
member this.GetGuild() = ctx.Guild
|
||||||
member this.GetInteractionId() = ctx.Id
|
member this.GetInteractionId() = ctx.Id
|
||||||
member this.GetChannel() = ctx.Channel
|
member this.GetChannel() = ctx.Channel
|
||||||
|
member this.GetContext() = ctx
|
||||||
|
|
||||||
let getTimeText isCooldown (timespan : TimeSpan) timestamp =
|
let getTimeText isCooldown (timespan : TimeSpan) timestamp =
|
||||||
let span =
|
let span =
|
||||||
|
Loading…
x
Reference in New Issue
Block a user