public async Task <HasActionsLeft> DoStateBasedAction( ActionString trigger, ActionString exitCondition, ActionString action, int planId, string planKey ) { if (await _session.ExistsPlan(planId)) { if (await _engine.PossessionSatisfiesLevel(exitCondition.location, exitCondition.first, exitCondition.second)) { await _session.DeletePlan(planId); return(HasActionsLeft.Available); } var hasActionsLeft = await DoAction(action); return(hasActionsLeft); } if (await _engine.PossessionSatisfiesLevel(trigger.location, trigger.first, trigger.second)) { await _session.CreatePlan(planId, planKey); return(await DoAction(action)); } return(HasActionsLeft.Available); }
public async Task <HasActionsLeft> LowerGenericMenace(string menace, int trigger, int clear, int planId, string planKey) { var triggerstr = new ActionString($"Menaces,{menace},{trigger}"); var exitc = new ActionString($"Menaces,{menace},<{clear}"); var action = new ActionString($"require,Menaces,{menace},<1"); return(await DoStateBasedAction(triggerstr, exitc, action, planId, planKey)); }
public async Task <HasActionsLeft> Acquire(ActionString actionstr, bool dryRun = false) { if (dryRun) { RecordAction(actionstr); return(HasActionsLeft.Consumed); } return(await Handler.DoAction(actionstr)); }
public async Task <HasActionsLeft> NavigateIntoAction(ActionString action) { await GoBackIfInStorylet(); if (_cachedList == null) { // was return false <- hasmoreactions? throw new Exception("invalid state after goback"); } await MoveIfNeeded(action.location); // this is a remnant from before the time of prereq in the acq engine // if (action.location == "carnival" && action.first != "Buy") // { // var hasActionsLeft = await EnsureTickets() // if (!hasActionsLeft) // { // return false; // } // } bool success = await EnterStorylet(action.first); if (_cachedList == null) { Log.Warning($"storylet {action.first} not found"); return(HasActionsLeft.Faulty); } var ac = new List <string> { action.second }; if (action.third != null) { ac.AddRange(action.third); } return(await PerformActions(ac)); }
public async Task <HasActionsLeft> HandleForcedAction() { var name = await _state.GetStoryletName(); var r = new Regex(name, RegexOptions.IgnoreCase); var simplekey = ForcedActionFile.simple.Keys.FirstOrDefault(k => r.IsMatch(k)); if (simplekey != null) { await _state.PerformAction(ForcedActionFile.simple[simplekey]); return(HasActionsLeft.Consumed); } var complexkey = ForcedActionFile.complex.Keys.FirstOrDefault(k => r.IsMatch(k)); if (complexkey != null) { foreach (var entry in ForcedActionFile.complex[complexkey]) { var total = entry.Conditions.Length; var satisfied = 0; foreach (var cond in entry.Conditions) { var a = new ActionString(cond); if (await _engine.PossessionSatisfiesLevel(a.location, a.first, a.second)) { satisfied++; } } if (total == satisfied) { await _state.PerformAction(entry.Action); return(HasActionsLeft.Consumed); } } } throw new Exception($"stuck in forced action named {name}, can't proceed without manual interaction"); }
public void RecordAction(ActionString action) { ActionHistory.Add(action); }
public async Task <HasActionsLeft> DoAction(ActionString action) { if (action.IsEmpty()) { Log.Error("cant do empty action"); return(HasActionsLeft.Faulty); } Log.Info($"doing action {action}"); // bazaar can usually be done even in storylet, i think? // require is best done doing its inventory checks before doing goback and move, to aviod extra liststorylet calls // inventory just needs to make sure we do gobackifinstorylet first if (action.location == "buy") { if (action.third == null) { throw new Exception($"invalid buy action {action}"); } var n = action.third[0].AsNumber(); if (!n.HasValue) { throw new Exception($"invalid buy action {action}"); } await _session.BuyPossession(action.first, action.second, n.Value); return(HasActionsLeft.Mismatch); } else if (action.location == "sell") { var n = action.second.AsNumber(); if (!n.HasValue) { throw new Exception($"invalid sell action {action}"); } await _session.SellPossession(action.first, n.Value); return(HasActionsLeft.Mismatch); } else if (action.location == "equip") { await _session.Equip(action.first); return(HasActionsLeft.Mismatch); } else if (action.location == "unequip") { await _session.Unequip(action.first); return(HasActionsLeft.Mismatch); } // todo require, but if faulty, return available, use for tea with vicar wich needs to start with a card // gives Stories,Advising the Loquacious Vicar,1 then // ladybones,More Tea with the Vicar,1 // ladybones,The Vicar's Search for Knowledge,the nature // ladybones,A Matter of Mortality with the Loquacious Vicar,ask around // ladybones,Looking to Warmer Climes with the Loquacious Vicar,remnants // ladybones,The Loquacious Vicar's Great Work,material else if (action.location == "require") { string level = action.third?.FirstOrDefault(); string tag = action.third?.Skip(1)?.FirstOrDefault(); var hasActionsLeft = await _engine.Require(action.first, action.second, level, tag); return(hasActionsLeft); } else if (action.location == "inventory") { if (action.third == null) { throw new Exception($"invalid inventory action {action}"); } var hasActionsLeft = await _state.DoInventoryAction(action.first, action.second, action.third[0]); return(hasActionsLeft); } else if (action.location == "grind_money") { return(await GrindMoney()); } else if (action.location == "handle_profession") { return(await HandleProfession()); } return(await _state.NavigateIntoAction(action)); }