Skip to content
This repository was archived by the owner on Nov 30, 2021. It is now read-only.

PersonAgent

Matthew Pohlmann edited this page Jan 1, 2014 · 1 revision

####Description All-purpose class for describing every person in SimCity201. When entering a structure or moving about the city the person takes on one or more roles, determining his/her behavior.

####Class Signature

public class PersonAgent extends Agent implements Person {}

####Data

String name;
CityPanel panel;
PersonState state;
Semaphore animation;
List<Role> roles;
PassengerRole passengerRole;
List<Action> planner;
Action currentAction;
CityTime time;
CityTime wakeupTime;
CityTime sleepTime;
double moneyOnHand;
int hungerLevel;
boolean hungerEnabled;
Vehicle vehicle;
Structure home;
Structure workplace;
Intention job;
CityTime workTime;
Structure currentLocation;
int bankAccountNumber;
List<ItemRequest> marketChecklist;
List<ItemRequest> inventory;
boolean tryToBuyCar;
public enum Intention {
    None,
    ResidenceSleep,
    ResidenceEat,
    ResidenceRelax,
    ResidenceLandLord,
    ResidencePayRent,
    BankTeller,
    BankGuard,
    BankWithdrawMoneyCustomer,
    BankDepositMoneyCustomer,
    BankTakeOutLoan,
    BankWithdrawMoneyBusiness,
    BankDepositMoneyBusiness,
    MarketManager,
    MarketEmployee,
    MarketConsumerGoods,
    MarketConsumerCar,
    RestaurantCook,
    RestaurantHost,
    RestaurantWaiter,
    RestaurantCashier,
    RestaurantCustomer
};
private class Action {
    Structure location;
    Intention intent;
    boolean active;
};
private enum PersonState {
    Sleeping,
    Awake,
    AtWork,
    Relaxing;
};

####Scheduler

if passengerRole.active then,
    passengerRole.pickAndExecuteAnAction();
    return true;
if state != Relaxing && Ǝ Role r in rolesr.active then,
    return r.pickAndExecuteAnAction();
if Ǝ Action a in plannera.active then,
    performAction(a);
    return true;
if Ǝ Action a in planner then,
    goToLocation(a);
    return true;
if state = Sleeping && time != Weekend && time = wakeupTime then,
    state = Awake;
    // If you need to pay rent
    if home != null && home.isApartment then,
        addActionToPlanner(Intention.ResidencePayRent, home, true);
    // The Residence Role will determine if there's enough time to eat at a Restaurant, or if eating at home is better
    addActionToPlanner(ResidenceEat, home, false);
    return true
if state = Sleeping && time == Weekend && time == wakeupTime + 90 minutes then,
    state = Awake;

    addActionToPlanner(ResidenceEat, home, false);
    return true
if state = Awake || Relaxing && time > workTime && time < workTime + 90 && time != Weekend then,
    if addActionToPlanner(job, workplace, true) then,
        state = AtWork;
        return true;
if state = Awake || Relaxing && time >= sleepTime then,
    passengerRole.msgStopRoaming();
    planner.clear();
    state = Sleeping;
    addActionToPlanner(ResidenceSleep, home, false);
    return true;
if state = Awake || Relaxing && moneyOnHand <= MONEYTHRESHOLD then,
    boolean performAction = true;
    if Ǝ Action a in plannera.intent = BankWithdrawMoneyCustomer then,
        performAction = false;
    if performAction && CityDirectory.getInstance().getBanks().size() > 0 then,
	addActionToPlanner(BankWithdrawMoneyCustomer, CityDirectory.getInstance().getRandomOpenBank(), false);
	state = PersonState.Awake;
	return true;
if state = Awake && currentLocation != home && hungerLevel >= HUNGRY then,
    boolean performAction = true;
    if Ǝ Action a in plannera.intent = RestaurantCustomer then,
        performAction = false;
    if performAction && CityDirectory.getInstance().getRestaurants().size() > 0 then,
	boolean starving = hungerLevel >= STARVING;
        addActionToPlanner(RestaurantCustomer, CityDirectory.getInstance().getRandomOpenRestaurant(), starving);
	return true;
if state = Awake || Relaxing && marketChecklist.size() > 0 then,
    boolean performAction = true;
    if Ǝ Action a in plannera.intent = MarketConsumerGoods then,
        performAction = false;
    if performAction && CityDirectory.getInstance().getMarkets().size() > 0 then,
	addActionToPlanner(MarketConsumerGoods, CityDirectory.getInstance().getRandomOpenMarket(), false);
	state = Awake;
	return true;
if state = Awake || Relaxing && home != null && currentLocation == home && hungerLevel >= HUNGRY then,
    boolean performAction = true;
    if Ǝ Action a in plannera.intent = ResidenceEat then,
        performAction = false;
    if performAction then,
	boolean starving = hungerLevel >= STARVING;
	if addActionToPlanner(ResidenceEat, home, starving) then,
	    state = Awake;
	    return true;
if state = Awake || Relaxing && tryToBuyCar then,
    boolean performAction = true;
    if Ǝ Action a in plannera.intent = MarketConsumerCar then,
        performAction = false;
    if performAction then,
	if addActionToPlanner(MarketConsumerCar, market, false) then,
	    state = Awake;
            tryToBuyCar = false;
	    return true;
if state = Awake then,
    if addActionToPlanner(ResidenceRelax, home, false) then,
	state = Relaxing;
	return true;
if state = Awake && !passengerRole.isRoaming() then,
    currentAction = null;
    passengerRole.setActive(true);
    passengerRole.startRoaming();

####Messages

// Updates the time so this Person can make appropriate time-based decisions
public void msgUpdateTime(CityTime newTime) {
    int minutesPassed = newTime - time;
    hungerLevel += (state == Sleeping) ? HUNGERPERMINUTE / 2 * minutesPassed : HUNGERPERMINUTE * minutesPassed;

    time.day = day;
    time.hour = hour;
    time.minute = minute;
    stateChanged();
}

####Actions

public void goToLocation(Action a) {
    a.active = true;
    if (!pasengerRole.isAtLocation(a.location)) {
	passengerRole.msgGoTo(a.location);
	currentLocation = null;
	passengerRole.setActive(true);
    }
}
private void performAction(Action a) {		
    Role newRole = a.location.getRole(a.intent);
    if (newRole == null) {
	planner.remove(a);
	return;
    }
		
    boolean haveRole = false;
    for (Role r : roles) {
	if (r.getClass().isInstance(newRole)) {
	    r.setPerson(this);
	    r.startInteraction(a.intent);
	    r.setActive(true);
	    haveRole = true;
	    break;
        }
    }
		
    if (!haveRole) {
	roles.add(newRole);
	newRole.setPerson(this);
	newRole.startInteraction(a.intent);
	newRole.setActive(true);
    }
		
    currentAction = a;
    planner.remove(a);
}
private boolean addActionToPlanner(Intention intent, Structure location, boolean highPriority) {
    if (intent == null || intent == Intention.None || location == null) {
	return false;
    }
		
    Action temp = new Action();
    temp.location = location;
    temp.intent = intent;
    if (!highPriority) {
	planner.add(temp);
    } else {
	planner.add(0, temp);
    }
    return true;
}

####Role-Related

public void removeRole(Role toRemove) {
    roles.remove(toRemove);
}
public void goOffWork() {
    this.state = PersonState.Awake;
}
public void justAte() {
    this.hungerLevel = FULL;
}
public void addMoney(double amount) {
    this.moneyOnHand += amount;
}
public void removeMoney(double amount) {
    this.moneyOnHand -= amount;
}
public void doneMoving(Structure newLocation) {
    currentLocation = newLocation;
}
public void addIntermediateActions(Role from, LinkedList<Intention> intents, boolean returnToCurrentAction) {		
    // Deactivate sending Role
    if (from != null) {
        from.setActive(false);
    }
    int numActivities = intents.size();
    boolean succeeded = false;
		
    while (intents.size() > 0) {
	// Create a new action with high priority and put it at front of planner
	Intention intent = intents.removeLast();
	switch (intent) {
	case ResidenceSleep: succeeded = this.addActionToPlanner(intent, home, true); break;
	case ResidenceEat: succeeded = this.addActionToPlanner(intent, home, true); break;
	case BankWithdrawMoneyCustomer: succeeded = this.addActionToPlanner(intent, CityDirectory.getInstance().getRandomBank(), true); break;
	case BankDepositMoneyCustomer: succeeded = this.addActionToPlanner(intent, CityDirectory.getInstance().getRandomBank(), true); break;
	case BankTakeOutLoan: succeeded = this.addActionToPlanner(intent, CityDirectory.getInstance().getRandomBank(), true); break;
	case BankWithdrawMoneyBusiness: succeeded = this.addActionToPlanner(intent, CityDirectory.getInstance().getRandomBank(), true); break;
	case BankDepositMoneyBusiness: succeeded = this.addActionToPlanner(intent, CityDirectory.getInstance().getRandomBank(), true); break;
	case MarketConsumerGoods: succeeded = this.addActionToPlanner(intent, CityDirectory.getInstance().getRandomMarket(), true); break;
        case MarketConsumerCar: succeeded = this.addActionToPlanner(intent, CityDirectory.getInstance().getRandomMarket(), true); break;
	case RestaurantCustomer: succeeded = this.addActionToPlanner(intent, CityDirectory.getInstance().getRandomRestaurant(), true); break;
	default: {
	    return;
	}
	}
    }
		
    // If Role requests that the PersonAgent return after, add that action back at the correct position
    if (returnToCurrentAction && succeeded) {
	currentAction.active = false;
	planner.add(numActivities, currentAction);
    } else if (returnToCurrentACtion && !succeeded) {
        currentAction.active = false;
        planner.add(numActivities - 1, currentAction);
    }
}

Wiki Home | Design Home

Clone this wiki locally