直接贴代码吧,c#模拟的,新建一个控制台项目,然后全部拷贝进去运行即可。
planner部分应该是从目标到当前状态的倒叙a*搜索比较合适,因为我模拟的比较简单,这部分就直接略过了,也就是说在这个项目中所有原子化的action都能直接实现当前状态到目标。
写的比较快,有些地方命名不严格,有些地方随便写的名字。
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Threading;
namespace ConsoleApp1 {
public class AIAction {
public string name;
public Dictionary<string, object> condition=new Dictionary<string, object>();
public Dictionary<string, object> effect=new Dictionary<string, object>();
public delegate void Work();
public Work work;
public AIAction(Work w) {
work = w;
}
public void DoWork() {
work();
}
}
public class AIGoal {
public string name;
public Dictionary<string, object> condition=new Dictionary<string, object>();
}
public class Planner {
public void SetPlan(List<AIAction> _actions,AIGoal _goal) {
for(int i = 0; i < _actions.Count; i++) {
foreach(KeyValuePair<string,object> pair in _actions[i].effect) {
bool isFinish = false;
foreach(KeyValuePair<string,object> p in _goal.condition) {
if (pair.Key == p.Key && (int)pair.Value == (int)p.Value) {
isFinish = true;
_actions[i].DoWork();
}
}
}
}
}
}
public class AI {
public List<AIAction> aIActions = new List<AIAction>();
public AIGoal currentGoal = new AIGoal();
public Planner planner = new Planner();
public void PullTrigger(string _condition) {
if (_condition == "hungry") {
currentGoal = new AIGoal();
currentGoal.name = "not hungry";
currentGoal.condition["hungry=?"] = 100;
}else if (_condition == "tired") {
currentGoal = new AIGoal();
currentGoal.name = "not tired";
currentGoal.condition["energy=?"] = 100;
}
planner.SetPlan(aIActions, currentGoal);
}
}
public class Cow {
private int hungry = 100;
private int energy = 100;
private AI ai =new AI();
public Cow() {
AIAction action = new AIAction(Sleep);
action.name = "sleep";
action.condition["energy<?"] = 20;
action.effect["energy=?"] = 100;
ai.aIActions.Add(action);
AIAction aIAction = new AIAction(Eat);
aIAction.name = "eat";
aIAction.condition["hungry<?"] = 20;
aIAction.effect["hungry=?"] = 100;
ai.aIActions.Add(aIAction);
}
public void Eat() {
hungry = 100;
Console.WriteLine("i m eating");
}
public void Sleep() {
energy = 100;
Console.WriteLine("i m asleep");
}
public void decreaseHungry() {
hungry -= 10;
if(hungry<10)
ai.PullTrigger("hungry");
}
public void decreaseTired() {
energy -= 5;
if(energy<10)
ai.PullTrigger("tired");
}
public void TempSetHungry() {
hungry = 10;
ai.PullTrigger("hungry");
}
public void TempSetTired() {
energy = 10;
ai.PullTrigger("tired");
}
}
public class Program {
public Cow cow=new Cow();
static void Main(string[] args) {
Program p = new Program();
const int SLEEPTIME = 300;
Console.WriteLine("q= quit");
Console.WriteLine("w= hungry");
Console.WriteLine("e= tired");
while(true){
p.cow.decreaseHungry();
p.cow.decreaseTired();
p.IO();
Console.WriteLine("----------------------");
Thread.Sleep(SLEEPTIME);
}
}
async void IO() {
await Task.Run(() => {
ConsoleKeyInfo key = Console.ReadKey();
if (key.KeyChar == 'q') {
Environment.Exit(0);
}else if (key.KeyChar == 'w') {
cow.TempSetHungry();
}else if (key.KeyChar == 'e') {
cow.TempSetTired();
}
});
}
}
}