-
Notifications
You must be signed in to change notification settings - Fork 216
/
Copy pathInventoryAction.cs
143 lines (134 loc) · 5.73 KB
/
InventoryAction.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
using AdaptiveCards;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Schema;
using Microsoft.Teams.AI.AI;
using Microsoft.Teams.AI.AI.Action;
using QuestBot.Models;
using QuestBot.State;
using System.Text.Json;
namespace QuestBot.Actions
{
public partial class QuestBotActions
{
[Action("inventory")]
public async Task<bool> InventoryAsync([ActionTurnContext] ITurnContext turnContext, [ActionTurnState] QuestState turnState, [ActionEntities] Dictionary<string, object> entities)
{
ArgumentNullException.ThrowIfNull(turnContext);
ArgumentNullException.ThrowIfNull(turnState);
var data = GetData(entities);
var action = (data.Operation ?? string.Empty).Trim().ToLowerInvariant();
switch (action)
{
case "update":
await UpdateListAsync(turnContext, turnState, data);
return true;
case "list":
return await PrintListAsync(turnContext, turnState);
default:
await turnContext.SendActivityAsync($"[inventory.{action}]");
return true;
}
}
/// <summary>
/// Prints the user's inventory to the conversation.
/// </summary>
private async Task<bool> PrintListAsync(ITurnContext context, QuestState state)
{
var items = state.User!.Inventory;
if (items != null && items.Count > 0)
{
state.Temp!.ListItems = items;
state.Temp!.ListType = "inventory";
_application.AI.Prompts.Variables["listType"] = state.Temp!.ListType;
_application.AI.Prompts.Variables["listItems"] = JsonSerializer.Serialize(state.Temp!.ListItems);
_application.AI.Prompts.Variables["name"] = state.User!.Name ?? string.Empty;
var newResponse = await _application.AI.CompletePromptAsync(context, state, "ListItems", null, default);
if (!string.IsNullOrEmpty(newResponse))
{
var card = ResponseParser.ParseAdaptiveCard(newResponse);
if (card != null)
{
await context.SendActivityAsync(MessageFactory.Attachment(new Attachment
{
ContentType = AdaptiveCard.ContentType,
Content = card.Card
}));
state.Temp.PlayerAnswered = true;
return true;
}
}
await UpdateDMResponseAsync(context, state, ResponseGenerator.DataError());
}
else
{
await UpdateDMResponseAsync(context, state, ResponseGenerator.EmptyInventory());
}
return false;
}
/// <summary>
/// Updates the user's inventory based on the given data.
/// </summary>
private static async Task UpdateListAsync(ITurnContext context, QuestState state, DataEntities data)
{
var newItems =
state.User!.Inventory == null ?
new ItemList() :
new ItemList(state.User!.Inventory);
// Remove items first
var changes = new List<string>();
var changeItems = ItemList.FromText(data.Items);
foreach (var removeItem in changeItems)
{
// Normalize the items name and count
// - This converts 'coins:1' to 'gold:10'
var normalizedItem = ItemList.MapTo(removeItem.Key, removeItem.Value);
if (string.IsNullOrEmpty(normalizedItem.Key))
{
continue;
}
if (normalizedItem.Value > 0)
{
// Add the item
if (newItems.ContainsKey(normalizedItem.Key))
{
newItems[normalizedItem.Key] += normalizedItem.Value;
}
else
{
newItems[normalizedItem.Key] = normalizedItem.Value;
}
changes.Add($"+{normalizedItem.Value} ({normalizedItem.Key})");
}
else if (normalizedItem.Value < 0)
{
// remove the item
var keyToRemove = newItems.SearchItem(normalizedItem.Key);
if (!string.IsNullOrEmpty(keyToRemove))
{
if (normalizedItem.Value + newItems[keyToRemove] > 0)
{
changes.Add($"{normalizedItem.Value} ({keyToRemove})");
newItems[keyToRemove] += normalizedItem.Value;
}
else
{
// Hallucinating number of items in inventory
changes.Add($"{newItems[keyToRemove]} ({keyToRemove})");
newItems.Remove(keyToRemove);
}
}
else
{
// Hallucinating item as being in inventory
changes.Add($"{normalizedItem.Value} ({normalizedItem.Key})");
}
}
}
// Report inventory changes to user
var playerName = state.User.Name?.ToLowerInvariant() ?? string.Empty;
await context.SendActivityAsync($"{playerName}: {string.Join(", ", changes)}");
// Save inventory changes
state.User.Inventory = newItems;
}
}
}