游戏人工智能之状态驱动智能体改进(三)
之前在忙考试,耽误了几天时间。今天我们继续之前的代码。
我们发现状态机实现的矿工行为总是固定不变的,于是我引入了天气作为不确定的因素,天气分为晴天、多云和下雨。晴天时,挖矿会更让人觉得口渴;下雨天时,矿工会回家,如果矿工非常疲倦,那么他回家就会睡觉,如果不是很累,那么矿工也会从事娱乐活动–网购,当然网购是要花钱的。现在和之前不同,喝水也要花钱购买。如果矿工入不敷出,那么他就会破产。
我们在之前代码的基础上进行修改(这次的代码相对来说要复杂一些,我加上注释方便阅读):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace SDIB
{
enum Weather
{
Sunny,Rainy,Cloudy
}
//随机生成天气
class WeatherEvent
{
public Weather getWeather()
{
Weather[] weathers = Enum.GetValues(typeof(Weather)) as Weather[];
Random random = new Random();
Weather weather = weathers[random.Next(0, weathers.Length)];
return weather;
}
}
//挖矿
class DigNugget
{
public int money;
public int gold;
public int tired;
public int health;
public Weather weather;
public int count;
public delegate void MinerEventHandler(Object listener,MinerEventArgs e);
public event MinerEventHandler Miner;
public class MinerEventArgs : EventArgs
{
public readonly int money;
public readonly int tired;
public readonly int health;
public MinerEventArgs(int money, int tired, int health)
{
this.money = money;
this.tired = tired;
this.health = health;
}
}
protected virtual void OnActive(MinerEventArgs e)
{
if (Miner != null)
{
Miner(this, e);
}
}
public void Update()
{
gold = 0;
WeatherEvent weatherAction = new WeatherEvent();
weather = weatherAction.getWeather();
while (true)
{
count++;
//如果计数大于5天气就会变化
if (count >= 5)
{
count = 0;
weather = weatherAction.getWeather();
}
if (gold < 0)
{
break;
}
//晴天挖矿会更加口渴
if(weather == Weather.Sunny){
tired ++;
health -= 3;
money++;
Console.WriteLine("天气:晴天");
Console.WriteLine("挖矿中");
Thread.Sleep(1000);
}
//多云和之前一样
else if (weather == Weather.Cloudy)
{
tired++;
health--;
money++;
Console.WriteLine("天气:多云");
Console.WriteLine("挖矿中");
Thread.Sleep(1000);
}
MinerEventArgs mea = new MinerEventArgs(money, tired, health);
OnActive(mea);
//下雨了回家
if (weather == Weather.Rainy)
{
Console.WriteLine("天气:下雨");
Console.WriteLine("下雨了,回家躲雨");
Thread.Sleep(1000);
GoHome.Update(this, mea);
continue;
}
if (tired >= 10)
{
Console.WriteLine("累了,回家睡觉");
Thread.Sleep(1000);
//Miner += GoHome.Update;
GoHome.Update(this, mea);
continue;
}
if (health <= 0)
{
Console.WriteLine("渴了,去酒吧喝酒");
Thread.Sleep(1000);
//Miner += GoBar.Update;
GoBar.Update(this, mea);
continue;
}
if (money >= 3)
{
Console.WriteLine("包满了,去银行换钱");
Thread.Sleep(1000);
//Miner += GoBank.Update;
GoBank.Update(this, mea);
continue;
}
}
}
}
class GoHome
{
public static void Update(Object listener, DigNugget.MinerEventArgs e)
{
DigNugget mine = (DigNugget)listener;
bool isSleep = false;
while (true)
{
//计数大于变换天气
if (mine.count >= 5)
{
mine.count = 0;
WeatherEvent weatherAction = new WeatherEvent();
mine.weather = weatherAction.getWeather();
}
//下雨、疲劳小于5,网购
if (mine.weather == Weather.Rainy && mine.tired <= 5 && isSleep == false)
{
Console.WriteLine("下雨了,不出去,在家网购");
Thread.Sleep(1000);
mine.gold--;
mine.count += 5;
//网购需要花钱,矿工没钱了就会破产
if (mine.gold < 0)
{
Console.WriteLine("矿工破产了");
break;
}
Console.WriteLine("剩余存款:" + mine.gold);
continue;
}
//否则睡觉
else if (mine.tired > 0)
{
Console.WriteLine("睡觉中");
Thread.Sleep(1000);
isSleep = true;
mine.tired --;
mine.count ++;
//睡醒了如果发现不下雨就去挖矿
if (mine.tired <= 0 && mine.weather != Weather.Rainy)
{
Console.WriteLine("睡醒了");
isSleep = false;
if (mine.weather != Weather.Rainy)
{
Console.WriteLine("去挖矿");
Thread.Sleep(1000);
break;
}
}
}
//如果不下雨了就去挖矿
else if (mine.weather != Weather.Rainy)
{
Console.WriteLine("去挖矿");
Thread.Sleep(1000);
break;
}
}
}
}
//去银行存钱,每存一次钱金钱数加1
class GoBank
{
public static void Update(Object listener, DigNugget.MinerEventArgs e)
{
DigNugget mine = (DigNugget)listener;
mine.money = 0;
mine.count++;
mine.gold++;
Console.WriteLine("存钱中,存款:"+mine.gold);
Thread.Sleep(1000);
Console.WriteLine("继续去金矿干活");
Thread.Sleep(1000);
}
}
//去酒吧
class GoBar
{
public static void Update(Object listener, DigNugget.MinerEventArgs e)
{
DigNugget mine = (DigNugget)listener;
mine.health = 10;
mine.count++;
mine.gold--;
//喝酒也要花钱,如果没钱就会破产
if (mine.gold < 0)
{
Console.WriteLine("矿工破产了");
return;
}
Console.WriteLine("喝水中,剩余存款:" + mine.gold);
Thread.Sleep(1000);
Console.WriteLine("不渴了,去金矿");
Thread.Sleep(1000);
}
}
//main函数
class Program
{
static void Main(string[] args)
{
DigNugget miner = new DigNugget();
miner.money = 0;
miner.tired = 0;
miner.health = 10;
miner.Update();
}
}
}
这样我们的矿工就显得智能多了:
当然有时候矿工也会很倒霉(有些不合理):
其实这个程序还有可以改进的地方,比如可以加入房租,每隔固定时间就要交房租,或者在去往银行的途中有几率遇到小偷,遭遇小偷后包里的矿就没了,只能回去继续挖矿等等。当然条件越多矿工生存越艰难,所以我们也可以对矿物进行枚举,分为铜矿、银矿、金矿,不同的矿物价值不同,如果挖到金矿那矿工也可以在家休息很久了(前提是去银行途中没有遇到小偷。。)。总而言之,我们的状态机实现了我们想要的功能,但是还比较单一,在接下来我们尝试加上一些社群行为。
如果有什么疑问可以留言>_<