Step5: 多层次代理的交互

目前为止,我们编写的代理行为都是代理本身来控制,那么如何实现代理族B来控制代理族A的行为呢?比如,我们为建筑添加一个人群管控的功能,当人群进入建筑时,其行为受到管控,直到建筑允许放行,才能从建筑中出来,要实现这样的复杂交互,我们要做的有以下几点:

  • 为建筑添加人群管控行为: let_people_leavelet_people_enter

  • 建筑族中创建人群族的子族群 people_in_building ,当人群进入建筑后,变为建筑族的一员,但保留了人群族的所有属性。

species building {
    ...
    //在建筑族中添加人群族的子族群people_in_building,其行为为空
    species people_in_building parent: people schedules: [] {
    }
    ...
    //定义人群进入建筑的行为
    reflex let_people_enter {
    //捕获进入建筑的人群,将其改为子族群people_in_building的一员
    capture (people inside self where (each.target = nil)) as: people_in_building;
    }
    //定义人群离开建筑的行为
    reflex let_people_leave {
    //计算进入建筑的人的停留时长
    ask people_in_building {
        staying_counter <- staying_counter + 1;
    }
    //以staying_counter / staying_coeff的概率释放子族群people_in_building的代理至世界代理中的people族
    release people_in_building where (flip(each.staying_counter / staying_coeff)) as: people in: world {
        //其目标为随机一栋建筑的任意地点
        target <- any_location_in(one_of(building));
    }
    }
    ...
}

schedules可以理解为时间调度表,将schedules设置为空,则代理行为均失效。

现在,我们将建筑的显示方式改为:

  • 建筑中没有人时显示为灰色

  • 建筑中感染人数比例小于0.5时显示为绿色

  • 建筑中感染人数比例大于0.5时显示为红色

因为人群分离出了子族群,因此我们在全局定义中统计感染人数的方法也需要更新。

accumulate:accumulate 和 collect 类似,区别在与accumulate 返回的是列表,collect 返回值可以是任何容器。

6.5.1 在建筑族中创建人群子族

本节完整代码如下:

Last updated

Was this helpful?