public GeneralNPC(CharacterNPC character, Vector3 position, IWalkable terrain, IControlable entity) { this.character = character; this.terrain = terrain; this.entity = entity; this.position3D = position; this.position2D = terrain.Get2DMapPosition(this.position3D); this.taskStack = new Stack <NpcTask>(); this.taskMove = new Traveling(new Astar()); this.fightMove = new Traveling(new Astar()); //init start status this.currentStatus = new Status(); this.currentStatus.hp = character.hp; this.currentStatus.mana = character.mana; this.currentStatus.energy = 100; this.currentStatus.position = this.position2D; this.currentStatus.enemySeen = 0; this.currentStatus.alive = true; this.currentStatus.nearEnemies = new List <IActing>(); this.targetCell = this.position2D; aiMap = Map.GetInstance(); this.npcMap = aiMap.getRelatedMap(this.position2D, this.visualRange); }
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); } }
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); }
/// <summary> /// ctor, initialize ai structures /// </summary> /// <param name="character">character of npc</param> /// <param name="position">position on which npc stands</param> /// <param name="terrain">terrain, where npc moves</param> /// <param name="entity">pointer on graphical representation of npc, used for changing position, making effects, ...</param> public NPC(CharacterNPC character, Vector3 position, IWalkable terrain, IControlable entity) { this.position3D = position; System.Drawing.Point xy = terrain.Get2DMapPosition(position); this.x = xy.X; this.y = xy.Y; this.character = character; this.visualRange = this.character.visualRange; this.currentStatus = new Status(); this.currentStatus.hp = character.hp; this.currentStatus.mana = character.mana; this.currentStatus.energy = 100; this.currentStatus.position = this.GetPosition2D(); this.currentStatus.enemySeen = 0; this.currentStatus.alive = true; this.currentStatus.nearEnemies = new List <IActing>(); this.entity = entity; this.terrain = terrain; this.taskStack = new Stack <NpcTask>(); this.taskMove = new Traveling(new Astar()); this.fightMove = new Traveling(new Astar()); this.targetCell = new System.Drawing.Point(x, y); this.aiMap = Map.GetInstance(); pathFinding = new Astar(); this.entity.ChangePosition(position); }
private void Init() { Bitmap bmp = new Bitmap(this.mapName); grid = new Grid(bmp, this.gridPanel); Logger.AddInfo("Map loaded: " + bmp.Width.ToString() + "; " + bmp.Height.ToString()); ai = new AICore(grid); string[] npcList = File.ReadAllLines(Directory.GetCurrentDirectory() + "\\Settings\\level1npc.ini"); characters = new WiccanRede.AI.CharacterNPC[npcList.Length]; Entity[] entities = new Entity[npcList.Length]; for (int i = 0; i < npcList.Length; i++) { try { characters[i] = new WiccanRede.AI.CharacterNPC("Settings\\" + npcList[i] + ".xml"); //ai.AddPlayer(characters[i], new Microsoft.DirectX.Vector3(i, i, i), new Entity(), "BasicFSM"); entities[i] = new Entity(characters[i], ai, "BasicFSM"); } catch (Exception ex) { Logging.Logger.AddWarning("Chyba pri nacitani NPC: " + npcList[i] + " - " + ex.ToString()); } } }
/// <summary> /// update for story line /// </summary> /// <param name="gameState">name of new game state</param> public void Update(string gameState) { control.Update(npcs, step, gameState); CharacterNPC playerChar = this.player.GetCharacter(); playerChar.level++; this.player.UpdateCharacter(playerChar); }
/// <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)); }
/// <summary> /// private ctor - singleton /// </summary> public GamePlayer(IControlable entity, CharacterNPC character) { //character = new CharacterNPC("Settings//NPC//Player.xml"); this.character = character; this.entity = entity; currentStatus = new Status(); this.currentStatus.hp = character.hp; this.currentStatus.mana = character.mana; this.currentStatus.energy = 100; this.currentStatus.position = AI.Map.GetInstance().GetTerrain().GetPlayerPosition(); this.currentStatus.enemySeen = 0; this.currentStatus.alive = true; instance = this; }
static void Main(string[] args) { Console.WriteLine("Testovaci konzole pro knihovnu AI."); Logger.InitLogger(); Logger.bWriteToOutput = true; dynamic = new DynamicProgramming(); mikelChar = new CharacterNPC("Settings/Mikel.xml"); TestDP(); Console.WriteLine("Stisknete libovolnou klavesu pro ukonceni... "); string end = Console.ReadLine(); Logger.Save(); }
/// <summary> /// register new ai controled player /// </summary> /// <param name="charakter">character of added npc</param> /// <param name="position">position where npc starts</param> /// <param name="entity">pointer to the graphical representation</param> /// <param name="fsmName">Name of finite state machine</param> /// <see cref="FSM"/> public void AddPlayer(CharacterNPC charakter, Vector3 position, IControlable entity, string controlMechanism, string actionDefinition) { NPC npc = new NPC(charakter, position, this.terrain, entity); npc.AttachActions(actionDefinition); if (controlMechanism.EndsWith(".lua")) { npc.AttachScript(controlMechanism); npcs.Add(npc); } else { AddNpcWithFsm(charakter, entity, controlMechanism, npc); } }
/// <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); }
/// <summary> /// register new ai controled player with script /// </summary> /// <param name="charakter">character of NPC</param> /// <param name="position">starting position</param> /// <param name="entity">pointer to the graphical representation</param> /// <param name="scriptPath">path to the script</param> public void AddPlayer(CharacterNPC charakter, Vector3 position, IControlable entity, string scriptPath) { NPC npc = new NPC(charakter, position, this.terrain, entity); npc.AttachScript(scriptPath); }
/// <summary> /// Adds the NPC with FSM. /// </summary> /// <param name="charakter">The charakter.</param> /// <param name="entity">The entity.</param> /// <param name="fsmName">Name of the FSM.</param> /// <param name="npc">The NPC.</param> private void AddNpcWithFsm(CharacterNPC charakter, IControlable entity, string fsmName, NPC npc) { FSM fsm = null; try { if (this.fsms != null && fsms.Count > 0) { Type type = fsms[0]; foreach (Type t in fsms) { if (t.Name == fsmName) { type = t; break; } } //ConstructorInfo ci = type.GetConstructor(new Type[] { type }); ConstructorInfo ci = type.GetConstructors()[0]; List <Object> constructorPars = new List <object>(); foreach (ParameterInfo pi in ci.GetParameters()) { if (pi.ParameterType.Name == "NPC") { constructorPars.Add(npc); } else if (pi.ParameterType.Name == "CharacterNPC") { constructorPars.Add(charakter); } else if (pi.ParameterType.Name == "IControlable") { constructorPars.Add(entity); } else if (pi.ParameterType.Name == "Map") { constructorPars.Add(this.map); } } fsm = (FSM)Activator.CreateInstance(type, constructorPars.ToArray()); //FSM fsm = (FSM)ci.Invoke(constructorPars.ToArray()); } } catch (Exception ex) { Logging.Logger.AddError("Chyba pri nacitani FSM: " + ex.ToString()); } if (fsm != null) { //Logging.Logger.AddInfo("pridavam npc na pozici: " + position.ToString()); npc.AttachFSM(fsm); //lock (this.npcs) { npcs.Add(npc); } } else { Logging.Logger.AddWarning("Nemohu pridat NPC " + charakter.name + ". Nenalezen zadny fsm"); } }
/// <summary> /// register human player /// </summary> /// <param name="entity">object for graphical representation</param> /// <param name="character">player's character</param> public void AddPlayer(IControlable entity, CharacterNPC character) { this.player = new GamePlayer(entity, character); }
public void UpdateCharacter(CharacterNPC character) { this.character = character; }
public Entity(CharacterNPC character, AICore ai, string fsmName) { ai.AddPlayer(character, new Vector3(), this, fsmName, ""); }
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); }