private bool CheckStats(CharacterNPC character, ref ConflictState exploringState) { if (exploringState.myMana < 0) { //not enaugh mana return(false); } else if (exploringState.myMana > character.mana) { return(false); } if (exploringState.enemyMana < 0) { exploringState.enemyMana = 0; } if (exploringState.enemyHP < 0) { exploringState.enemyHP = 0; } if (exploringState.myHP < 0) { exploringState.myHP = 0; } else if (exploringState.myHP > character.hp) { //heal over max hp return(false); } //else if (exploringState.myHP - character.hp < 50 // && exploringState.myHP - character.hp > 0) //{ // exploringState.myHP = character.hp; //} return(true); }
private void Recurse(ConflictState state, CharacterNPC character, CharacterNPC enemyChar, ActionType actinType, int step) { List <ConflictState> nextStates = GetSuccessors(state, character, enemyChar, actinType); DPItem item = new DPItem(); item.Probability = state.probability; item.State = state; item.Children = nextStates; if (!space.ContainsKey(item.GetHashCode())) { this.space.Add(item.GetHashCode(), item); } step++; if (step < this.stateSpaceDeep) { ConflictState successor; for (int i = 0; i < nextStates.Count; i++) { successor = nextStates[i]; if (this.stateSpace.Contains(successor)) { //Logger.AddInfo("DP: nalezena duplicita. " + successor.ToString()); continue; } if (successor.enemyHP <= 0) { Logger.AddInfo("DP:Nalezen cilovy stav " + successor.ToString()); successor.cost = 0; //step = this.stateSpaceDeep; nextStates[i] = successor; break; } else if (successor.myHP < character.hp / 4) { successor.cost = 100; nextStates[i] = successor; } this.stateSpace.Add(successor); //try //{ // if (!space.ContainsKey(successor.GetHashCode())) // { // space.Add(successor.GetHashCode(), successor); // } // else // { // //Logger.AddWarning("DP: chyba pri pridavani do hash tabulky..." + successor.ToString()); // } //} //catch (Exception) //{ // Logger.AddWarning("DP: chyba pri pridavani do hash tabulky..." + successor.ToString()); //} Recurse(successor, character, enemyChar, actinType, step); } //this.stateSpace.AddRange(nextStates); } }
public void Iterate(ConflictState state) { int h = 10; DPItem item = new DPItem(); if (!space.TryGetValue(state.GetHashCode(), out item)) { return; } for (int i = 0; i < iterationCount; i++) { foreach (KeyValuePair <int, DPItem> pair in space) { //int min = int.MaxValue; h = pair.Value.State.cost; ConflictState current = pair.Value.State; foreach (ConflictState s in pair.Value.Children) { h += s.probability * s.cost; //if (state.cost < min) //{ // min = state.cost; //} } pair.Value.State = current; } } }
/// <summary> /// evaluate given state-prob pair /// </summary> /// <param name="current">current confict state, without any applied actions</param> /// <param name="pairs">pairs to evaluate</param> /// <param name="character">npc character</param> /// <returns>calculated cost of given pairs</returns> private int ComputeCost(ConflictState current, StateProbPairs pairs, CharacterNPC character) { int cost = 0; ConflictState state; for (int i = 0; i < pairs.states.Count; i++) { state = pairs.states[i]; if (state.myHP > character.hp) { state.myHP = character.hp; } if (state.myMana > character.mana) { state.myMana = character.mana; } int myHpRating = 0, enemyHpRating = 0, boostRating = 0, manaRating = 0; if (state.myHP > current.myHP) { myHpRating = current.myHP; } else if (state.myHP < current.myHP) { myHpRating = current.myHP - state.myHP; //self harm } if (state.myMana - current.myMana >= 80) { manaRating = current.myMana; } else if (state.myMana < current.myMana) { manaRating = state.myMana - current.myMana; } if (state.enemyHP < current.enemyHP) { enemyHpRating = state.enemyHP; } boostRating = 0;// character.mana - state.myMana; int energyRating = (current.myEnergy - state.myEnergy) * 10; int timeRating = pairs.action.time / 10; int sum = myHpRating + enemyHpRating + boostRating + energyRating + manaRating + timeRating; sum *= (pairs.probabilities[i]); sum /= 100; cost += sum; } cost /= pairs.states.Count; return(cost); }
public void CreateStateSpace(ConflictState currentState, CharacterNPC character, CharacterNPC enemyChar, ActionType actinType) { Logging.Logger.StartTimer("Vytvareni statespace"); int step = 0; Recurse(currentState, character, enemyChar, actinType, step); Logging.Logger.StopTimer("Vytvareni statespace"); Logger.AddInfo("Velikost State space: " + this.stateSpace.Count.ToString()); Logger.AddInfo("Velikost space: " + this.space.Count.ToString()); this.bestActions.Capacity = this.stateSpace.Count; }
private bool CheckStats(CharacterNPC character, CharacterNPC enemyChar, ref ConflictState exploringState) { if (exploringState.enemyHP > enemyChar.hp) { return(false); } else if (exploringState.enemyHP < 0) { exploringState.enemyHP = 0; } return(CheckStats(character, ref exploringState)); }
public void DoAction(Action selectedAction, ConflictState state, string type) { if (type == "Defense") { //stronger healing this.currentStatus.hp = state.myHP + selectedAction.hpGot / 4; this.currentStatus.mana = state.myMana; this.currentStatus.energy = state.myEnergy; //weaker attack selectedAction.enemyHpTaken -= selectedAction.enemyHpTaken / 4; selectedAction.enemyHpTaken += this.character.level * this.character.power; //send action info into the game logic ActionInfo info = new ActionInfo(); info.action = selectedAction; info.targetPosition = this.targetedEnemy.GetPosition3D(); //info.targetPosition.Y += 80; info.startPosition = this.GetPosition3D(); info.npcName = this.character.name; info.targetName = this.TargetedEnemy.GetCharacter().name; this.GetEntity().Spell(info); this.targetedEnemy.GetEntity().GetHarm(); } else { //update my status with such as subtract my mana, add healed hp,.. this.currentStatus.hp = state.myHP; this.currentStatus.mana = state.myMana; this.currentStatus.energy = state.myEnergy; selectedAction.enemyHpTaken += this.character.level * this.character.power; //send action info into the game logic ActionInfo info = new ActionInfo(); info.action = selectedAction; info.targetPosition = this.targetedEnemy.GetPosition3D(); //info.targetPosition.Y += 80; info.startPosition = this.GetPosition3D(); info.npcName = this.character.name; info.targetName = this.TargetedEnemy.GetCharacter().name; this.GetEntity().Spell(info); this.targetedEnemy.GetEntity().GetHarm(); } }
public static ConflictState operator +(ConflictState state, Action action) { ConflictState newState = new ConflictState(); newState.cost = state.cost; newState.enemyEnergy = state.enemyEnergy; newState.enemyHP = state.enemyHP - action.enemyHpTaken; newState.enemyMana = state.enemyMana - action.enemyManaDrain; newState.enemyPosition = state.enemyPosition; //TODO dodelat posouvani npccek pri zasahu newState.enemySpeed = state.enemySpeed - 1 * (int)action.enemySpeedReduce; newState.myEnergy = state.myEnergy - action.myEnergyDrain; newState.myHP = state.myHP + action.hpGot; newState.myMana = state.myMana - action.manaDrain; newState.myPosition = state.myPosition; newState.mySpeed = state.mySpeed; return(newState); }
/// <summary> /// from generated state-prob pairs choose the best one and returns new Confict state /// </summary> /// <param name="myself">npc, which is choosing from actions</param> /// <param name="enemy">enemy npc on which is the target</param> /// <param name="priors">priors from npc character, useless for now</param> /// <param name="actionType">type of action</param> /// <returns>new confict state</returns> public ConflictState GetNextAction(IActing myself, IActing enemy, Priorities priors, out Action selectedAction) { ConflictState currentState = new ConflictState(myself.GetStatus(), enemy.GetStatus()); Priorities priorities = priors; CharacterNPC myChar = myself.GetCharacter(); //if (this.stateSpace.Count == 0) //{ // CreateStateSpace(currentState, myChar); //} List <StateProbPairs> expanders = Expand(currentState, myChar); StateProbPairs result = new StateProbPairs(); int lowestCost = int.MaxValue; int actionCost = int.MaxValue; foreach (StateProbPairs pairs in expanders) { //if (this.stateSpace.Contains(pairs)) //{ // Logging.Logger.AddInfo(pairs.ToString() + " je obsazeno"); //} actionCost = ComputeCost(currentState, pairs, myChar); if (actionCost < lowestCost && actionCost >= 0) { result = pairs; lowestCost = actionCost; } } if (result.states == null) { result.states.Add(currentState); Action empty = new Action(); empty.name = "empty"; empty.time = 5000; result.action = empty; result.probabilities.Add(100); } int index = 0; if (result.probabilities.Count > 1) { int randChoose = rand.Next(100); if (randChoose < result.probabilities[0]) { index = 0; } else if (randChoose < result.probabilities[0] + result.probabilities[1]) { index = 1; } else { if (result.states.Count > 2) { index = 2; } } } if (index >= result.states.Count) { index = 0; } Logging.Logger.AddInfo(myChar.name + ": " + result.action.ToString() + " proti " + enemy.GetCharacter().name + ", cost=" + lowestCost + ", efekt: " + index); myself.SetCoolDown(result.action.time); selectedAction = result.action; this.lastAction = selectedAction; //return result.states[index]; return(result.states[0]); }
/// <summary> /// apply actions on conflict state and by this generate followers of current confict state /// </summary> /// <param name="state"> current conflict state </param> /// <param name="character">character of npc, used for checking stats</param> /// <param name="actionType">action type, which says, what actions are available</param> /// <returns>List of state-probability pairs</returns> private List <StateProbPairs> Expand(ConflictState state, CharacterNPC character) { List <StateProbPairs> expanders = new List <StateProbPairs>(); //List<Action> actions = null; //switch (actionType) //{ // case ActionType.Attack: // actions = this.attackActions; // break; // case ActionType.Defense: // actions = this.defenseActions; // break; // default: // Logging.Logger.AddWarning("Spatny typ akce"); // return expanders; // //break; //} foreach (Action action in this.actions) { if (action.name == lastAction.name && action.name.StartsWith("Heal")) { break; } //TODO - spravit cooldownama StateProbPairs pairs = new StateProbPairs(); pairs.states = new List <ConflictState>(); pairs.probabilities = new List <int>(); ConflictState succesState; // = new ConflictState(); ConflictState noEffectState; // = new ConflictState(); ConflictState failState; // = new ConflictState(); succesState = state + action; //spell casted succesfull noEffectState = state; //casting has no effect, failState = state; // -action; //casting fail and harm caster failState.myHP -= action.enemyHpTaken; failState.myHP -= action.hpGot; int prob = action.probability; int noneProb = 100 - prob - failProb; int fail = failProb; //check and add to expanders if (CheckStats(character, ref succesState)) { pairs.states.Add(succesState); pairs.probabilities.Add(prob); if (action.probability != 100) { if (CheckStats(character, ref failState)) { pairs.states.Add(failState); pairs.probabilities.Add(fail); } //pairs.states.Add(noEffectState); //pairs.probabilities.Add(noneProb); } } pairs.action = action; if (pairs.states.Count > 0) { expanders.Add(pairs); } } return(expanders); }
private List <ConflictState> GetSuccessors(ConflictState state, CharacterNPC character, CharacterNPC enemyChar, ActionType actionType) { List <ConflictState> successors = new List <ConflictState>(); List <Action> actions = null; switch (actionType) { case ActionType.Attack: actions = this.attackActions; break; case ActionType.Defense: actions = this.defenseActions; break; default: Logging.Logger.AddWarning("DP: Spatny typ akce"); return(successors); //break; } ConflictState succesState = new ConflictState(); //ConflictState noEffectState = new ConflictState(); ConflictState failState = new ConflictState(); ConflictState enemySuccesState = new ConflictState(); ConflictState enemyFailState = new ConflictState(); foreach (Action action in actions) { if (action.probability == 100) { succesState = state + action; successors.Add(succesState); } else { //spell is casted by "this" npc succesState = state + action; //spell casted succesfull succesState.probability = action.probability; //noEffectState = state; //casting has no effect, failState = state; //casting fail and harm caster failState.myHP -= action.enemyHpTaken; failState.myHP -= action.hpGot; failState.probability = failProb; //spell is casted by this NPCs enemy enemySuccesState = state - action; enemySuccesState.probability = action.probability; enemyFailState = state; enemyFailState.enemyHP -= action.enemyHpTaken; enemyFailState.enemyHP -= action.hpGot; enemyFailState.probability = failProb; //check if states are valid if (CheckStats(character, enemyChar, ref enemyFailState)) { successors.Add(enemyFailState); } if (CheckStats(character, enemyChar, ref enemySuccesState)) { successors.Add(enemySuccesState); } if (CheckStats(character, enemyChar, ref succesState)) { successors.Add(succesState); } if (CheckStats(character, enemyChar, ref failState)) { successors.Add(failState); } } } return(successors); }
internal void CheckState(IActionSelection actionSelection) { if (this.actualState.IsEqual("Go")) { npc.Go(); } else if (this.actualState.IsEqual("Conflict") || this.actualState.IsEqual("Defense")) { if (npc.TargetedEnemy == null) { Logger.AddWarning(npc.GetCharacter().name + ": conflict, ale target je null"); return; } try { Status npcStatus = npc.GetStatus(); //Status enemyStatus = npc.TargetedEnemy.GetStatus(); //Logger.AddInfo(this.npc.character.name + ": " + npcStatus.ToString()); //ActionType type = (this.actualState.IsEqual("Confict") ? ActionType.Attack : ActionType.Defense); Action selectedAction; ConflictState state = actionSelection.GetNextAction(npc, npc.TargetedEnemy, npc.character.priors, out selectedAction); //do moving #region moving //if (rand.Next(100) < 80) { Point npcPos = this.npc.GetStatus().position; Point enemyPos = this.npc.GetTargetedEnemy().GetStatus().position; int dist = this.npc.CalculateDistance(npcPos, enemyPos); if (dist > 10 && this.npc.TargetedEnemy.GetCharacter().name == "Player") { this.npc.DoFightMove(enemyPos); } else if (dist > 4) { Point diff = new Point(); diff.X = enemyPos.X - npcPos.X; diff.Y = enemyPos.Y - npcPos.Y; Point goal = this.npc.GetStatus().position; //move with npc, try to stay at the "ideal" distance if (diff.X != 0 && diff.Y != 0) { goal.Offset(new Point(diff.X / Math.Abs(diff.X), diff.Y / Math.Abs(diff.Y))); } //don't want to divide by zero else if (diff.X == 0) { //diff.X++; goal.Offset(0, diff.Y / Math.Abs(diff.Y)); } else if (diff.Y == 0) { diff.Y++; goal.Offset(new Point(diff.X / Math.Abs(diff.X), 0)); } goal = LocationCorrection(goal); if (!Map.GetInstance().CellMap[goal.X, goal.Y].Block) { this.npc.DoFightMove(goal); } } else { Point goal = this.npc.GetStatus().position; double random = this.rand.NextDouble(); double random2 = this.rand.NextDouble(); int offset1 = 0; int offset2 = 0; if (random > 0.66) { offset1 = 1; } else if (random > 0.33) { offset1 = -1; } if (random2 > 0.66) { offset2 = 1; } else if (random2 > 0.33) { offset2 = -1; } //move randomly with NPC goal.Offset(offset1, offset2); goal = LocationCorrection(goal); if (!Map.GetInstance().CellMap[goal.X, goal.Y].Block) { this.npc.DoFightMove(goal); } } #endregion } this.npc.DoAction(selectedAction, state, this.actualState.GetName()); } catch (Exception ex) { Logger.AddWarning("Chyba pri vybirani akce: " + ex.ToString()); } } else if (this.actualState.IsEqual("RunAway")) { Point goal = new Point(); //Point p = new Point(); //p.X = this.npc.GetPosition2D().X - this.npc.GetTargetedEnemy().GetStatus().position.X; //p.Y = this.npc.GetPosition2D().Y - this.npc.GetTargetedEnemy().GetStatus().position.Y; //goal = this.npc.GetPosition2D(); //goal.Offset(p); int offset = 25; Point current = this.npc.GetPosition2D(); List <Point> locations = new List <Point>(); Point up = current; up.Offset(0, offset); up = LocationCorrection(up); locations.Add(up); Point down = current; down.Offset(0, -offset); down = LocationCorrection(down); locations.Add(down); Point left = current; left.Offset(-offset, 0); left = LocationCorrection(left); locations.Add(left); Point right = current; right.Offset(offset, 0); right = LocationCorrection(right); locations.Add(right); Point rightUp = current; rightUp.Offset(offset, offset); rightUp = LocationCorrection(rightUp); locations.Add(rightUp); Point leftUp = current; leftUp.Offset(-offset, offset); leftUp = LocationCorrection(leftUp); locations.Add(leftUp); Point leftDown = current; leftDown.Offset(-offset, -offset); leftDown = LocationCorrection(leftDown); locations.Add(leftDown); Point rightDown = current; rightDown.Offset(offset, -offset); rightDown = LocationCorrection(rightDown); locations.Add(rightDown); //find safest new location to run to int eval = 0; int bigest = 0; foreach (Point loc in locations) { foreach (IActing enemy in this.npc.GetStatus().nearEnemies) { eval += this.npc.CalculateDistance(enemy.GetStatus().position, loc); } if (eval > bigest) { bigest = eval; goal = loc; } eval = 0; } goal = LocationCorrection(goal); npc.DoFightMove(goal); } else if (this.actualState.IsEqual("Stand")) { //TODO - what to do in stand state? } else if (this.actualState.IsEqual("Seek")) { Point goal = this.npc.GetStatus().position; goal = this.npc.TargetedEnemy.GetStatus().position; //goal = LocationCorrection(goal); //if (!Map.GetInstance().CellMap[goal.X, goal.Y].Block) { this.npc.DoFightMove(goal); } } else if (this.actualState.IsEqual("Weakness")) { this.npc.Rest(); } else { Logger.AddWarning("BasicFSM: neznamy stav automatu - " + this.actualState); } }
private void CheckState(IActionSelection actionSelection) { if (this.actualState.IsEqual("Defense")) { if (npc.TargetedEnemy == null) { Logger.AddWarning("Villager- " + npc.GetCharacter().name + ": conflict, ale target je null"); return; } try { Status npcStatus = npc.GetStatus(); //Status enemyStatus = npc.TargetedEnemy.GetStatus(); Logger.AddInfo(this.npc.character.name + ": " + npcStatus.ToString()); //ActionType type = ActionType.Defense; //(this.actualState.IsEqual("Confict") ? ActionType.Attack : ActionType.Defense); Action selectedAction; ConflictState state = actionSelection.GetNextAction(npc, npc.TargetedEnemy, npc.character.priors, out selectedAction); this.npc.DoAction(selectedAction, state); } catch (Exception ex) { Logger.AddWarning("Chyba pri vybirani akce: " + ex.ToString()); } } else if (this.actualState.IsEqual("Stand")) { Point goal = this.npc.GetStatus().position; double random = rand.NextDouble(); double random2 = rand.NextDouble(); int offset1 = 0; int offset2 = 0; if (random > 0.66) { offset1 = 1; } else if (random > 0.33) { offset1 = -1; } if (random2 > 0.66) { offset2 = 1; } else if (random2 > 0.33) { offset2 = -1; } //move randomly with NPC goal.Offset(offset1, offset2); goal = LocationCorrection(goal); if (!Map.GetInstance().CellMap[goal.X, goal.Y].Block) { this.npc.DoFightMove(goal); } } else if (this.actualState.IsEqual("Talk")) { //TODO let's talk :) } }
public void DoAction(Action selectedAction, ConflictState state) { throw new Exception("The method or operation is not implemented."); }
private void CheckState(IActionSelection actionSelection) { if (this.actualState.IsEqual("Conflict") || this.actualState.IsEqual("Defense")) { if (npc.TargetedEnemy == null) { Logger.AddWarning("Straz- " + npc.GetCharacter().name + ": conflict, ale target je null"); return; } try { Status npcStatus = npc.GetStatus(); Status enemyStatus = npc.TargetedEnemy.GetStatus(); //Logger.AddInfo(this.npc.character.name + ": " + npcStatus.ToString()); //ActionType type = (this.actualState.IsEqual("Confict") ? ActionType.Attack : ActionType.Defense); Action selectedAction; ConflictState state = actionSelection.GetNextAction(npc, npc.TargetedEnemy, npc.character.priors, out selectedAction); //do moving //if (rand.Next(100) < 95) { Point npcPos = this.npc.GetStatus().position; Point enemyPos = this.npc.GetTargetedEnemy().GetStatus().position; if (this.npc.CalculateDistance(npcPos, enemyPos) > 4) { Point diff = new Point(); diff.X = enemyPos.X - npcPos.X; diff.Y = enemyPos.Y - npcPos.Y; Point goal = this.npc.GetStatus().position; //move with npc, try to stay at the "ideal" distance if (diff.X != 0 && diff.Y != 0) { goal.Offset(new Point(diff.X / Math.Abs(diff.X), diff.Y / Math.Abs(diff.Y))); } //don't want to divide by zero else if (diff.X == 0) { goal.Offset(new Point(0, diff.Y / Math.Abs(diff.Y))); } else if (diff.Y == 0) { goal.Offset(new Point(diff.X / Math.Abs(diff.X), 0)); } goal = LocationCorrection(goal); if (!Map.GetInstance().CellMap[goal.X, goal.Y].Block) { this.npc.DoFightMove(goal); } } else { Point goal = this.npc.GetStatus().position; goal = RandomMove(goal); if (!Map.GetInstance().CellMap[goal.X, goal.Y].Block) { this.npc.DoFightMove(goal); } } } this.npc.DoAction(selectedAction, state); } catch (Exception ex) { Logger.AddWarning("Chyba pri vybirani akce: " + ex.ToString()); } } else if (this.actualState.IsEqual("Seek")) { Point goal = this.npc.GetStatus().position; goal = this.npc.TargetedEnemy.GetStatus().position; //goal = LocationCorrection(goal); //if (!Map.GetInstance().CellMap[goal.X, goal.Y].Block) { this.npc.DoFightMove(goal); } } else if (this.actualState.IsEqual("Stand")) { //Point goal = this.npc.GetStatus().position; //goal = RandomMove(goal); //if (!Map.GetInstance().CellMap[goal.X, goal.Y].Block) //{ // this.npc.DoFightMove(goal); //} } else if (this.actualState.IsEqual("Talk")) { //TODO let's talk :) } else if (this.actualState.IsEqual("Start")) { if (this.npc.CurrentTask.checkpoints != null) { this.React(AiEvents.ready); } } }
public void DoAction(Action selectedAction, ConflictState state) { }