Tactical Control Group¶
This is (mostly) automagic documentation for our ongoing Python work. What does Tactical Control actually do? Somebody needs to write a description for that...
Documentation for FSM Examples¶
Finite State Machines with some extra goodies attached.
Generic FSM Modules¶
Modules in this section are not specific to WestWorld2; they can be used anywhere we need an FSM.
base_entity.py:¶
Module for defining managing game-type entities.
Use the BaseEntity class for agents that need a unique ID as well as periodic updating and messaging functionality. The EntityManager class provides a simple interface for automatic management.
Messages are sent via an instance of the MessageDispatcher class. This works with an EntityManager in order to serve as a kind of post office. Both immediate and delayed messages are possible; see the class description.
-
class
base_entity.
BaseEntity
(myID, postoffice)¶ Abstract Base Class for objects with an ID, update, and messaging.
Parameters: - myID (int) – The unique ID assigned to this entity.
- postoffice (MessageDispatcher) – Where this entity will send its messages.
Raises: ValueError
– If the requested ID is invalid.Notes
Because of how messaging is implemented, each entity needs a unique ID. We use a private class variable to make sure that ID’s are not repeated. Since ID’s aren’t recycled, we can’t accidentally send a message or otherwise refer to an entity that is no longer valid.
-
get_id
()¶ Returns the ID of this entity.
-
update
()¶ Update method that will be called each step This must be implemented by subclasses.
-
receive_msg
(message)¶ Message handler; must be implemented my subclasses.
Parameters: message (tuple) – A message constructed using the telegram() function.
-
class
base_entity.
EntityManager
¶ Manager class for objects of type BaseEntity
-
register
(entity)¶ Add an instance of BaseEntity to this manager.
Parameters: entity (BaseEntity) – An entity that has been instantiated outside of this class.
-
remove
(entity)¶ Remove an instance of BaseEntity from this manager.
Notes
Since BaseEntity’s are instantiated/deleted outside of this class, removing only affects this manager’s behavior. This function checks whether entity has the correct type, so deleting entity before removing it from the manager shouldn’t be an issue.
-
get_entity_from_id
(ent_id)¶ Returns an entity object from its ID.
Returns: The entity corresponding to ent_id. If this ID isn’t registered, returns None. Return type: BaseEntity
-
update
()¶ Calls the update() method of all registered entities.
Note: The order in which entities are called in not known.
-
start_all_fsms
()¶ Starts the FSM for each entity that has one.
-
-
class
base_entity.
MessageDispatcher
(clock_now, ent_mgr)¶ Class for posting/handling messages between entities.
Parameters: - clock_now (function()) – A function that returns a numerical value. This is used to represent the current time to control delivery of delayed messages.
- ent_mgr (EntityManager) – Used by this class to lookup an entity, given its ID.
-
discharge
(receiver, message)¶ Passes a message to a given recipient.
-
post_msg
(delay, send_id, rec_id, msg_type, extra=None)¶ Add a message to the queue for immediate or delayed dispatch.
-
dispatch_delayed
()¶ Dispatches messages from the delayed queue.
state_machine.py¶
Module containing basic FSM functionality.
All states should be derived from the State class, see its documentation.
Use STATE_NONE as a concrete null state. We need only a single instance.
An instance of BaseEntity can be given FSM functionality as follows:
- fsm = StateMachine(entity)
- fsm.set_state(current, global, previous), the last two are optional
- entity.fsm = fsm
- In entity’s update() method, call self.fsm.update()
In entity’s receive_msg() method, calling entity.fsm.handle_msg(message) will allow the FSM to route messages to the appropriate state logic: first to the current state, then to the global state.
-
class
state_machine.
State
¶ Base class for all states.
States derived from this base class should override the methods below, though all of them are optional. Each method takes a parameter, agent, which is the BaseEntity that is using that state. This allows multiple entities to reuse the same state logic.
-
enter
(agent)¶ Code to execute immediately when changing to this state.
-
execute
(agent)¶ Code to execute each time this state is executed.
-
leave
(agent)¶ Code to execute just before changing from this state.
-
on_msg
(agent, message)¶ Code to execute when a message is received.
Note
When overriding this method, we need to return a boolean that indicates if the message was succesfully handled. The messaging functions use this boolean to redirect the message elsewhere if a given state is unable to handle it.
-
-
state_machine.
STATE_NONE
= <state_machine.State object>¶ Use this as a concrete null state; we need only a single instance.
-
class
state_machine.
StateMachine
(owner)¶ Finite State Machine with messaging capability.
After instantiating a new StateMachine, use the set_state() method below in order to explicity initialize the states. Otherwise, this FSM will sit around and do nothing on update.
Parameters: owner (BaseEntity) – The entity using this instance of the FSM. -
set_state
(cur, glo=None, pre=None)¶ Manually set owner’s states without triggering state change logic.
Parameters:
-
start
()¶ Start the FSM by executing global & current state’s enter() methods.
Note
This is an attempt to fix the issue of BaseEntities not having access to messaging during their __init__() functions. This calls the enter() methods of the global state first, then the FSM’s current state.
-
update
()¶ Execute the owner’s global state (if any), then current state.
-
change_state
(newstate)¶ Switches owner to a new state, calling leave/enter methods.
Parameters: - newstate (State) – The FSM will switch to this state.
- Note (Both the current and new states must be valid, otherwise nothing) –
- happen and we'll stay in the current state. (will) –
-
revert_state
()¶ Reverts owner to its previous state; useful for state blips.
-
handle_msg
(message)¶ Used by the FSM to route received messages.
The message is first passed to the current state, which tries to handle it. If the current state fails to do so, the message is then passed to the global state, if one exists.
Parameters: message (tuple) – A message constructed using the telegram() function. Returns: True if the message was handled by either the current or global state; False otherwise. Return type: bool
-
Westworld2 Specifics¶
Example usage of the Generic FSM Modules.
Sample Output¶
- Miner Bob : Walkin’ to the gold mine...
- Wife Elsa : Housework ain’t gonna do itself!
- Miner Bob : Found me a gold nugget!
- Wife Elsa : Workin’ round the house...tra-la-lah-la-lah...
- Miner Bob : Found me two nuggets, whaddaya know!
- Miner Bob : Done diggin’ fer now.
- Miner Bob : Headin’ to bank, yessiree!
- Miner Bob : Now depositin’ 3 gold...
- Miner Bob : Saved myself 3 gold...soon’ll be rich!
- Miner Bob : Leavin’ the bank...
- Miner Bob : Walkin’ to the gold mine...
- Wife Elsa : Thar’s a goat in mah yard!
- Wife Elsa : Shoo, ya silly goat!
- Goat : Nom nom flowers
- Miner Bob : Keep on a-diggin’...
- Wife Elsa : Shoo, ya silly goat!
- Goat : Scampers away
- Headin’ on home...
- Wife Elsa : Housework ain’t gonna do itself!
- Miner Bob : Keep on a-diggin’...
- Wife Elsa : Thar’s a goat in mah yard!
- Wife Elsa : Shoo, ya silly goat!
- Goat : Nom nom flowers
- Miner Bob : Keep on a-diggin’...
- Wife Elsa : Shoo, ya silly goat!
- Goat : Nom nom flowers
- Miner Bob : Found me a gold nugget!
- Wife Elsa : Shoo, ya silly goat!
- Goat : Nom nom flowers
- Miner Bob : Found me two nuggets, whaddaya know!
- Miner Bob : Done diggin’ fer now.
- Miner Bob : Headin’ to bank, yessiree!
- Wife Elsa : Shoo, ya silly goat!
- Goat : Nom nom flowers
- Miner Bob : Now depositin’ 3 gold...
- Miner Bob : Saved myself 6 gold...soon’ll be rich!
- Miner Bob : Leavin’ the bank...
- Miner Bob : Walkin’ to the gold mine...
- Wife Elsa : Shoo, ya silly goat!
- Goat : Nom nom flowers
- Miner Bob : Found me a gold nugget!
- Miner Bob : Done diggin’ fer now.
- Miner Bob : Headin’ to the saloon fer a drink...
- Wife Elsa : Shoo, ya silly goat!
- Goat : Nom nom flowers
- Miner Bob : Havin’ a whiskey...mighty refreshin’!
- Miner Bob : Leavin’ the saloon fer now...
- Miner Bob : Walkin’ to the gold mine...
- Wife Elsa : Shoo, ya silly goat!
- Goat : Scampers away
- Headin’ on home...
- Wife Elsa : Housework ain’t gonna do itself!
- Miner Bob : Found me a gold nugget!
- Wife Elsa : Thar’s a goat in mah yard!
- Wife Elsa : Shoo, ya silly goat!
- Goat : Nom nom flowers
- Miner Bob : Keep on a-diggin’...
- Miner Bob : Done diggin’ fer now.
- Miner Bob : Headin’ to the saloon fer a drink...
- Wife Elsa : Shoo, ya silly goat!
- Goat : Scampers away
- Headin’ on home...
- Wife Elsa : Housework ain’t gonna do itself!
- Miner Bob : Havin’ a whiskey...mighty refreshin’!
- Miner Bob : Leavin’ the saloon fer now...
- Miner Bob : Walkin’ to the gold mine...
- Miner Bob : Found me two nuggets, whaddaya know!
- Miner Bob : Done diggin’ fer now.
- Miner Bob : Headin’ to bank, yessiree!
- Wife Elsa : Workin’ round the house...tra-la-lah-la-lah...
- Miner Bob : Now depositin’ 4 gold...
- Miner Bob : Saved myself 10 gold...soon’ll be rich!
- Miner Bob : Leavin’ the bank...
- Miner Bob : Day’s a finished, headin’ on home!
- Wife Elsa : Gonna rustle up some mighty fine stew!
- Wife Elsa : Wrassalin’ with dinner...
- Miner Bob : Zzzzzz....
- Wife Elsa : Wrassalin’ with dinner...
- Miner Bob : Zzzzzz....
- Wife Elsa : Thar’s a goat in mah yard!
- Wife Elsa : Shoo, ya silly goat!
- Goat : Scampers away
- Wife Elsa : Heading back to the kitchen...
- Wife Elsa : Gonna rustle up some mighty fine stew!
- Miner Bob : Zzzzzz....
- Wife Elsa : Wrassalin’ with dinner...
- Wife Elsa : Stew’s ready, come an’ git it!
- Miner Bob : I hears ya’, lil’ lady...
- Wife Elsa : Headin’ to the dinner table...
- Miner Bob : That’s some might fine stew...thank ya much, Elsa!
- Miner Bob : Now where was I...?
- Wife Elsa : Eatin’ the stew...I outdone myself this time.
- Wife Elsa : Housework ain’t gonna do itself!
- Miner Bob : Zzzzzz....
- Wife Elsa : Workin’ round the house...tra-la-lah-la-lah...
- Miner Bob : Zzzzzz....
- Wife Elsa : Workin’ round the house...tra-la-lah-la-lah...
- Wife Elsa : Done got me a message, oh my!
- Miner Bob : Zzzzzz....
- Wife Elsa : Workin’ round the house...tra-la-lah-la-lah...
- Miner Bob : Zzzzzz....
- Wife Elsa : Thar’s a goat in mah yard!
- Wife Elsa : Shoo, ya silly goat!
- Goat : Scampers away
- Headin’ on home...
- Wife Elsa : Housework ain’t gonna do itself!
- Miner Bob : Done restin’ fer now, back to work!
- Miner Bob : Walkin’ to the gold mine...
- Wife Elsa : Workin’ round the house...tra-la-lah-la-lah...
- Miner Bob : Found me a gold nugget!
- Miner Bob : Done diggin’ fer now.
- Miner Bob : Headin’ to the saloon fer a drink...
- Wife Elsa : Workin’ round the house...tra-la-lah-la-lah...
- Miner Bob : Havin’ a whiskey...mighty refreshin’!
- Wife Elsa : Workin’ round the house...tra-la-lah-la-lah...
- Miner Bob : Havin’ a whiskey...mighty refreshin’!
- Wife Elsa : Thar’s a goat in mah yard!
- Wife Elsa : Shoo, ya silly goat!
- Goat : Nom nom flowers
- Miner Bob : Havin’ a whiskey...mighty refreshin’!
- Miner Bob : Leavin’ the saloon fer now...
- Miner Bob : Walkin’ to the gold mine...
- Wife Elsa : Shoo, ya silly goat!
- Goat : Nom nom flowers
- Miner Bob : Keep on a-diggin’...
- Wife Elsa : Shoo, ya silly goat!
- Goat : Nom nom flowers
- Miner Bob : Found me two nuggets, whaddaya know!
- Miner Bob : Done diggin’ fer now.
- Miner Bob : Headin’ to bank, yessiree!
- Wife Elsa : Shoo, ya silly goat!
- Goat : Nom nom flowers
- Miner Bob : Now depositin’ 3 gold...
- Miner Bob : Saved myself 13 gold...soon’ll be rich!
- Miner Bob : Leavin’ the bank...
- Miner Bob : Day’s a finished, headin’ on home!
- Wife Elsa : Shoo, ya silly goat!
- Goat : Nom nom flowers
- Miner Bob : Zzzzzz....
- Wife Elsa : Shoo, ya silly goat!
- Goat : Nom nom flowers
- Miner Bob : Zzzzzz....
- Wife Elsa : Shoo, ya silly goat!
- Goat : Nom nom flowers
- Miner Bob : Zzzzzz....
- Wife Elsa : Shoo, ya silly goat!
- Goat : Scampers away
- Headin’ on home...
- Wife Elsa : Housework ain’t gonna do itself!
- Wife Elsa : Gonna rustle up some mighty fine stew!
- Miner Bob : Done restin’ fer now, back to work!
- Miner Bob : Walkin’ to the gold mine...
- Wife Elsa : Wrassalin’ with dinner...
- Miner Bob : Found me a gold nugget!
- Miner Bob : Done diggin’ fer now.
- Miner Bob : Headin’ to the saloon fer a drink...
- Wife Elsa : Wrassalin’ with dinner...
- Miner Bob : Havin’ a whiskey...mighty refreshin’!
- Wife Elsa : Wrassalin’ with dinner...
- Wife Elsa : Stew’s ready, come an’ git it!
- Miner Bob : Done got me a message! Yeehaw!
- Miner Bob : Havin’ a whiskey...mighty refreshin’!
- Miner Bob : Leavin’ the saloon fer now...
- Miner Bob : Walkin’ to the gold mine...
- Wife Elsa : Thar’s a goat in mah yard!
- Wife Elsa : Shoo, ya silly goat!
- Goat : Scampers away
- Wife Elsa : Headin’ to the dinner table...
- Miner Bob : Found me two nuggets, whaddaya know!
- Miner Bob : Done diggin’ fer now.
- Miner Bob : Headin’ to bank, yessiree!
- Wife Elsa : Thar’s a goat in mah yard!
- Wife Elsa : Shoo, ya silly goat!
- Goat : Nom nom flowers
- Miner Bob : Now depositin’ 3 gold...
- Miner Bob : Saved myself 16 gold...soon’ll be rich!
- Miner Bob : Leavin’ the bank...
- Miner Bob : Day’s a finished, headin’ on home!
- Wife Elsa : Shoo, ya silly goat!
- Goat : Scampers away
- Wife Elsa : Headin’ to the dinner table...
- Miner Bob : Zzzzzz....
- Wife Elsa : Eatin’ the stew...I outdone myself this time.
- Wife Elsa : Housework ain’t gonna do itself!
- Wife Elsa : Gonna rustle up some mighty fine stew!
- Miner Bob : Zzzzzz....
- Wife Elsa : Wrassalin’ with dinner...
- Miner Bob : Done restin’ fer now, back to work!
- Miner Bob : Walkin’ to the gold mine...
- Wife Elsa : Wrassalin’ with dinner...
- Miner Bob : Found me a gold nugget!
- Miner Bob : Done diggin’ fer now.
- Miner Bob : Headin’ to the saloon fer a drink...
- Wife Elsa : Wrassalin’ with dinner...
- Miner Bob : Havin’ a whiskey...mighty refreshin’!
- Miner Bob : Leavin’ the saloon fer now...
- Miner Bob : Walkin’ to the gold mine...
- Wife Elsa : Wrassalin’ with dinner...
- Wife Elsa : Stew’s ready, come an’ git it!
- Miner Bob : Done got me a message! Yeehaw!
- Miner Bob : Keep on a-diggin’...
- Wife Elsa : Eatin’ the stew...I outdone myself this time.
- Wife Elsa : Housework ain’t gonna do itself!
- Miner Bob : Found me a gold nugget!
- Miner Bob : Done diggin’ fer now.
- Miner Bob : Headin’ to the saloon fer a drink...
- Wife Elsa : Thar’s a goat in mah yard!
- Wife Elsa : Shoo, ya silly goat!
- Goat : Nom nom flowers
- Miner Bob : Havin’ a whiskey...mighty refreshin’!
- Miner Bob : Leavin’ the saloon fer now...
- Miner Bob : Walkin’ to the gold mine...
- Wife Elsa : Shoo, ya silly goat!
- Goat : Nom nom flowers
- Miner Bob : Keep on a-diggin’...
- Wife Elsa : Shoo, ya silly goat!
- Goat : Nom nom flowers
- Miner Bob : Keep on a-diggin’...
- Wife Elsa : Shoo, ya silly goat!
- Goat : Scampers away
- Headin’ on home...
- Wife Elsa : Housework ain’t gonna do itself!
- Miner Bob : Found me a gold nugget!
- Miner Bob : Done diggin’ fer now.
- Miner Bob : Headin’ to bank, yessiree!
- Wife Elsa : Thar’s a goat in mah yard!
- Wife Elsa : Shoo, ya silly goat!
- Goat : Nom nom flowers
- Miner Bob : Now depositin’ 3 gold...
- Miner Bob : Saved myself 19 gold...soon’ll be rich!
- Miner Bob : Leavin’ the bank...
- Miner Bob : Day’s a finished, headin’ on home!
- Wife Elsa : Shoo, ya silly goat!
- Goat : Nom nom flowers
- Miner Bob : Zzzzzz....
- Wife Elsa : Shoo, ya silly goat!
- Goat : Nom nom flowers
- Miner Bob : Zzzzzz....
- Wife Elsa : Shoo, ya silly goat!
- Goat : Nom nom flowers
- Miner Bob : Zzzzzz....
- Wife Elsa : Shoo, ya silly goat!
- Goat : Nom nom flowers
- Miner Bob : Zzzzzz....
- Wife Elsa : Shoo, ya silly goat!
- Goat : Scampers away
- Headin’ on home...
- Wife Elsa : Housework ain’t gonna do itself!
- Wife Elsa : Gonna rustle up some mighty fine stew!
- Miner Bob : Zzzzzz....
- Wife Elsa : Wrassalin’ with dinner...
- Miner Bob : Zzzzzz....
- Wife Elsa : Wrassalin’ with dinner...
- Miner Bob : Done restin’ fer now, back to work!
- Miner Bob : Walkin’ to the gold mine...
- Wife Elsa : Wrassalin’ with dinner...
- Wife Elsa : Stew’s ready, come an’ git it!
- Miner Bob : Done got me a message! Yeehaw!
- Miner Bob : Found me a gold nugget!
- Miner Bob : Done diggin’ fer now.
- Miner Bob : Headin’ to the saloon fer a drink...
- Wife Elsa : Thar’s a goat in mah yard!
- Wife Elsa : Shoo, ya silly goat!
- Goat : Scampers away
- Wife Elsa : Headin’ to the dinner table...
- Miner Bob : Havin’ a whiskey...mighty refreshin’!
- Wife Elsa : Eatin’ the stew...I outdone myself this time.
- Wife Elsa : Housework ain’t gonna do itself!
- Miner Bob : Havin’ a whiskey...mighty refreshin’!
- Wife Elsa : Thar’s a goat in mah yard!
- Wife Elsa : Shoo, ya silly goat!
- Goat : Scampers away
- Headin’ on home...
- Wife Elsa : Housework ain’t gonna do itself!
- Miner Bob : Havin’ a whiskey...mighty refreshin’!
- Miner Bob : Leavin’ the saloon fer now...
- Miner Bob : Walkin’ to the gold mine...
- Miner Bob : Keep on a-diggin’...
- Wife Elsa : Workin’ round the house...tra-la-lah-la-lah...
- Miner Bob : Found me a gold nugget!
- Wife Elsa : Workin’ round the house...tra-la-lah-la-lah...
- Miner Bob : Found me two nuggets, whaddaya know!
- Miner Bob : Done diggin’ fer now.
- Miner Bob : Headin’ to bank, yessiree!
- Wife Elsa : Thar’s a goat in mah yard!
- Wife Elsa : Shoo, ya silly goat!
- Goat : Nom nom flowers
- Miner Bob : Now depositin’ 4 gold...
- Miner Bob : Saved myself 23 gold...soon’ll be rich!
- Miner Bob : Leavin’ the bank...
- Miner Bob : Day’s a finished, headin’ on home!
- Wife Elsa : Shoo, ya silly goat!
- Goat : Nom nom flowers
- Miner Bob : Zzzzzz....
- Wife Elsa : Shoo, ya silly goat!
- Goat : Scampers away
- Headin’ on home...
- Wife Elsa : Housework ain’t gonna do itself!
- Wife Elsa : Gonna rustle up some mighty fine stew!
- Miner Bob : Zzzzzz....
- Wife Elsa : Thar’s a goat in mah yard!
- Wife Elsa : Shoo, ya silly goat!
- Goat : Scampers away
- Wife Elsa : Heading back to the kitchen...
- Wife Elsa : Gonna rustle up some mighty fine stew!
- Miner Bob : Zzzzzz....
- Wife Elsa : Wrassalin’ with dinner...
- Miner Bob : Zzzzzz....
- Wife Elsa : Wrassalin’ with dinner...
- Wife Elsa : Stew’s ready, come an’ git it!
- Miner Bob : I hears ya’, lil’ lady...
- Wife Elsa : Headin’ to the dinner table...
- Miner Bob : That’s some might fine stew...thank ya much, Elsa!
- Miner Bob : Now where was I...?
- Wife Elsa : Eatin’ the stew...I outdone myself this time.
- Wife Elsa : Housework ain’t gonna do itself!
- Wife Elsa : Done got me a message, oh my!
- Miner Bob : Done restin’ fer now, back to work!
- Miner Bob : Walkin’ to the gold mine...
- Wife Elsa : Workin’ round the house...tra-la-lah-la-lah...
- Miner Bob : Found me two nuggets, whaddaya know!
- Miner Bob : Done diggin’ fer now.
- Miner Bob : Headin’ to the saloon fer a drink...
- Wife Elsa : Thar’s a goat in mah yard!
- Wife Elsa : Shoo, ya silly goat!
- Goat : Nom nom flowers
- Miner Bob : Havin’ a whiskey...mighty refreshin’!
- Wife Elsa : Shoo, ya silly goat!
- Goat : Scampers away
- Headin’ on home...
- Wife Elsa : Housework ain’t gonna do itself!
- Miner Bob : Havin’ a whiskey...mighty refreshin’!
- Miner Bob : Leavin’ the saloon fer now...
- Miner Bob : Walkin’ to the gold mine...
- Wife Elsa : Workin’ round the house...tra-la-lah-la-lah...
- Miner Bob : Found me a gold nugget!
- Miner Bob : Done diggin’ fer now.
- Miner Bob : Headin’ to bank, yessiree!
- Wife Elsa : Workin’ round the house...tra-la-lah-la-lah...
- Miner Bob : Now depositin’ 3 gold...
- Miner Bob : Saved myself 26 gold...soon’ll be rich!
- Miner Bob : Whee, doggy! A winner is y’all!
- Elapsed time: 79 clock ticks.
gamedata.py:¶
Game-wide constants.
Game Entities¶
- BOB: Miner Bob, Elsa’s husband
- ELSA: Wife Elsa, scourge of wandering goats
Locations¶
- SHACK: Bob and Elsa’s humble home
- MINE: Gold mine. Dig for nuggets here!
- BANK: A bank, duh. Deposit nuggets here!
- SALOON: Quench yer thirst here!
- YARD: Frequently invaded by flower-eating goats!
ent_miner.py:¶
Miner Entity using simple FSM functionality.
-
class
ent_miner.
Miner
(*args)¶ Miner Bob.
Note: The constructor doesn’t take any actual args, but this syntax is needed to call the __init__ method of the superclass. I’m not sure that we need to do so here, but it will be a useful reminder for later.
-
update
()¶ Increases thirst and updates the FSM logic.
-
change_location
(newlocation)¶ Move to another location
Location constants are enumerated in gamedata.py
-
change_gold
(amount)¶ Add/subtract the amount of gold currently carried
Parameters: amount (int) – Amount of gold to add (or subtract, if negative)
-
pockets_full
()¶ Queries whether this entity is carrying enough gold.
-
add_fatigue
(amount=1)¶ Increases the current fatigue of this entity.
-
remove_fatigue
(amount=1)¶ Remove fatigue from this entity, but not below zero.
-
is_thirsty
()¶ Queries if this entity has too much current thirst.
-
remove_thirst
(amount)¶ Remove thirst from this entity, but not below zero.
-
work_done
()¶ Returns True if more than 10 gold in the bank.
Note
Fix this! Once there is 10 gold or more in the bank, the Miner will go home after each bank deposit. We don’t want that.
-
-
class
ent_miner.
GlobalMinerState
¶ Global state that just handles message.
Prints that a message was received, with no further details.
-
class
ent_miner.
DigInMine
¶ Go to the mine and dig until pockets full or thirsty.
State Transitions:
- When pockets are full -> DepositInBank
- When thirsty -> DrinkAtSaloon
-
class
ent_miner.
DepositInBank
¶ Go to the bank and deposit all carried gold.
State Transitions:
- If more than 25 gold in the bank -> GameOver
- If work_done (enough money in bank) -> GoHomeAndRest
- Otherwise -> DigInMine
-
class
ent_miner.
DrinkAtSaloon
¶ Go to the saloon and drink until thirst is quenched
State Transitions:
- When no longer thirsty -> revert to previous
-
class
ent_miner.
GoHomeAndRest
¶ Go home and rest.
When Miner Bob enters this state, he sends Elsa a message to start cooking the stew. He’s apparently impatient or a workaholic, because he will go back to the mine once fully rested, even if he’s not eaten yet. Poor Elsa!
State Transitions:
- Once fully rested -> DigInMine
- If stew is ready and is still in SHACK -> MinerEatStew
-
class
ent_miner.
MinerEatStew
¶ Eat that tasty stew, and thank yer lovely wife!
Food removes fatigue, of course.
State Transitions:
- After a single execute() to eat stew -> revert to previous
ent_wife.py:¶
Wife Entity using simple FSM functionality
-
class
ent_wife.
Wife
(*args)¶ Wife Elsa, scourge of the goats.
Note: The constructor doesn’t take any actual args, but this syntax is needed to call the __init__ method of the superclass. I’m not sure that we need to do so here, but it will be a useful reminder for later.
-
update
()¶ Updates the FSM logic, and nothing else.
-
-
class
ent_wife.
GlobalWifeState
¶ Wife State: Global state that handles messages and chases goats!
State Transitions (these change the current state, not the global one):
- Goat in yard -> ChaseGoat
- on_msg MINER_HOME -> Cook Stew
-
class
ent_wife.
DoHouseWork
¶ Old West misogyny, yeehaw!
Note
Elsa is apparently a lot tougher than her husband, since she never gets tired or thirsty! We should probably give her some more interesting things to do...a good exercise in FSM design/coding!
This state has no transitions; those are handled by GlobalWifeState.
-
class
ent_wife.
CookStew
¶ More bro-gramming at it’s finest, but the code is quite involved.
On entering this state, Elsa posts a delayed STEW_READY message so that she knows the cooking is done. Once she receives this, she then sends an immediate STEW_READY to Bob before sitting down to eat herself.
State Transitions:
- on_msg STEW_READY -> WifeEatStew
-
class
ent_wife.
WifeEatStew
¶ Eat that tasty stew!
State Transitions:
- After one execute() to eat stew -> DoHouseWork
-
class
ent_wife.
ChaseGoat
¶ Head to the yard and shoo that goat!
Goats are stubborn critters, so there’s a random chance that Elsa fails to shoo the goat. But she’ll keep at it until the job’s done!
Goats also demand undivided attention, but Elsa has a good memory. Any message received by this state will be forwarded to Elsa in the next update() cycle. This means that if Bob comes home whilst Elsa’s chasing a goat, she’ll still receive the MINER_HOME message when she’s done.
State Transitions:
- Successfully shoos the goat -> revert to previous
Documentation for Vector-Based Code¶
Homegrown vector code for use in Python.
Generic Vector Code¶
For handling math-type vectors in Python.
point2d.py¶
A Two-Dimensional Point/Vector Class
There are surely much better implementations of this sort of thing, for various definitions of ‘better.’ This module is designed to by easily readable and portable, without having to fuss with installation/importing of modules such as numpy that would probably perform better.
-
class
point2d.
Point2d
(x=0, y=0)¶ Creates a 2d vector, defaulting to <0,0>.
Parameters: - x (float) – x-coordinate (defaults to 0).
- y (float) – y-coordinate (defaults to 0).
-
zero
()¶ Set all coordinates of this point to zero.
>>> a = Point2d(3,-2) >>> print(a) Point2d: <3.000000000, -2.000000000> >>> a.zero() >>> print(a) Point2d: <0.000000000, 0.000000000>
-
ntuple
()¶ Returns the coordinates of this point in a Python tuple.
Example
>>> a = Point2d(3,-2) >>> print(a) Point2d: <3.000000000, -2.000000000> >>> a.ntuple() (3.0, -2.0)
-
scm
(scalar)¶ Scalar multiplication of this vector.
Example
>>> a = Point2d(1,-2) >>> print(a.scm(3.5)) Point2d: <3.500000000, -7.000000000> >>> print(a.scm(-2)) Point2d: <-2.000000000, 4.000000000>
-
rotated_by
(angle, use_deg=False)¶ Get this vector rotated anticlockwise.
Parameters: - angle (int or float) – Directed anticlockwise angle to rotate by,
- degrees (boolean) – If True, angle is in degrees. Otherwise radians (default)
Example
>>> from math import pi >>> a = Point2d(2,-2) >>> print(a.rotated_by(pi)) Point2d: <-2.000000000, 2.000000000> >>> print(a.rotated_by(-pi/3)) Point2d: <-0.732050808, -2.732050808> >>> print(a.rotated_by(90,True)) Point2d: <2.000000000, 2.000000000>
-
norm
()¶ Get the norm (length) of this vector.
Example
>>> Point2d(1,-2).norm() 2.23606797749979
-
sqnorm
()¶ Get the squared norm (length) of this vector.
Example
>>> Point2d(1,-2).sqnorm() 5.0
-
unit
()¶ Get a unit vector in the same direction as this one.
Note
Be aware of round-off errors; see the example below.
Example
>>> a = Point2d(1,-2) >>> print(a.unit()) Point2d: <0.447213595, -0.894427191> >>> a.unit().norm() 0.9999999999999999
-
normalize
()¶ Rescale this vector to have length 1.
Note
Be aware of round-off errors; see the example below.
Example
>>> a = Point2d(1,-2) >>> a.normalize() >>> print(a) Point2d: <0.447213595, -0.894427191> >>> a.norm() 0.9999999999999999
-
truncate
(maxlength)¶ Rescale this vector if needed so its length is not too large.
Parameters: maxlength (float) – Upper limit on the length. If the current length exceeds this, the vector will be rescaled. Returns: True if rescaling was done, False otherwise. Return type: bool Examples
>>> a = Point2d(1,-2) >>> a.truncate(1.0) True >>> print(a) Point2d: <0.447213595, -0.894427191> >>> b = Point2d(-1,2) >>> b.truncate(5.0) False >>> print(b) Point2d: <-1.000000000, 2.000000000>
-
scale_to
(mag)¶ Change this vector’s scale to the given magnitude.
Parameters: mag (float) – New magnitude for this vector; negative will reverse direction. Example
>>> a = Point2d(2,3) >>> a.scale_to(-4.2) >>> print(a) Point2d: <-2.329740824, -3.494611236> >>> a.norm() 4.2
-
angle
()¶ Get the polar angle of this vector in radians; range (-pi,pi]
Raises: ZeroDivisionError: If called on a zero vector. Examples
>>> Point2d(1,-2).angle() -1.1071487177940904 >>> Point2d(1,0).angle() 0.0 >>> Point2d(0,1).angle() 1.5707963267948966 >>> Point2d(-1,0).angle() 3.141592653589793 >>> Point2d(-2,-2).angle() -2.356194490192345 >>> Point2d(0,0).angle() Traceback (most recent call last): ... ZeroDivisionError: float division by zero
-
proj
(direction)¶ Get the orthogonal projection of this vector onto another.
Parameters: direction (Point2d) – The vector we project onto; not required to be a unit vector. Returns: The unique vector v2 such that self = q*v2 + v3, where v2 is in the span of direction and v2 and v3 are orthogonal. Return type: Point2d Example
>>> a = Point2d(2,4) >>> b = Point2d(3,-2) >>> print(a.proj(b)) Point2d: <-0.461538462, 0.307692308> >>> print(b.proj(a)) Point2d: <-0.200000000, -0.400000000>
Notes
If you want both v2 and v3, use Point2d.resolve(direction) instead.
-
resolve
(direction)¶ Orthogonal decomposition of this vector in a given direction.
Parameters: direction (Point2d) – The vector we project onto; not required to be a unit vector. Returns: v2,v3 such that self = q*v2 + v3, where v2 is in the span of direction and v2 and v3 are orthogonal. Return type: Point2d, Point2d Example
>>> a = Point2d(2,-3) >>> b = Point2d(1,4) >>> print(a.resolve(b)[0]) Point2d: <-0.588235294, -2.352941176> >>> print(a.resolve(b)[1]) Point2d: <2.588235294, -0.647058824> >>> print(a.resolve(b)[0]+a.resolve(b)[1]) Point2d: <2.000000000, -3.000000000>
-
left_normal
()¶ Returns the left-facing normal of this vector.
Example
>>> print(Point2d(1,-2).left_normal()) Point2d: <2.000000000, 1.000000000>
-
class
point2d.
RollingVectorMean
(n_size=2)¶ Helper class for computing rolling averages.
Parameters: n_size (int) – Number of previous values to average over; must be at least 2. Note
Experimental, will raise NotImplementedError on __init__
Documentation for Graph-Theoretic Code¶
Homegrown graph theory code for use in Python.
Generic Graph Theory Code¶
Graph-theoretic operations in Python.
base_graph_simple.py¶
base_gridgraph.py¶
Basic GridGraph class. Demo uses Pygame for rendering.
-
class
base_gridgraph.
GridGraph
(cols=2, rows=2, dx=1.0, dy=1.0)¶ A regular rectangular grid with Manhattan/diagonal neighborhoods.
Parameters: - cols (int) – Number of node columns (in the horizontal dimension).
- rows (int) – Number of node rows (in the vertical dimension).
- dx (float) – Edge weight between horizontally adjacent nodes.
- dy (float) – Edge weight between vertically adjacent nodes.
-
is_node
(node)¶ Check for a valid node (even if it’s inactive).
-
is_not_inactive
()¶ Check for an active node (does not check for validity).
Note
For performance reasons, this simply checks if the node with grid coordinates (x,y) is in the grid’s inactive list.
-
edge_cost
(node0, node1)¶ Get the edge cost between two nodes. :returns: float :rtype: The edge cost, or INF if the nodes are not adjacent.
Raises: IndexError : If either node is invalid.
-
active_neighbors
(node)¶ Get a list of active neighbors for the given node.
Parameters: node (2-tuple of int) – Grid coordinates of the given node. Note
For performance reasons, this does not check if node is valid.
base_graph.py¶
Module for various type of graph nodes/edges. WORK IN PROGRESS!
-
base_graph.
INVALID_NODE_ID
= -1¶ Any reference to this index is treated as being a nonexistant node.
-
class
base_graph.
BaseGraphNode
(node_id, **kwargs)¶ Base class for various types of graph nodes.
Parameters: - node_id (int) – ID to assign this node, to allow consistency with external information.
- kwargs (any, optional) – Additional attributes can be set using keyword arguments. Each key (except node_id) sets an instance variable with the same name. There is no error-checking in the base class, but subclasses may override this.
Note
Subclasses should call the base __init__() method (via super) to set the node ID and any extra keyword arguments. The base class keeps a master directory of nodes by id, which can be accessed using the module function get_node(node_id).
-
base_graph.
get_node
(node_id)¶ A handle to the node with the given id; None for invalid nodes.
-
class
base_graph.
EasyGraphNode
(node_id, **kwargs)¶ A BaseGraphNode with anonymous directed edges.
Adjacency is stored locally per node, using a dictionary keyed by node ID, Entries can then represent edge information (weight, label, etc.), but there is no way to access edges independently. To modify adjacency, use either the make_edges() or remove_edges() method on the source node.
Parameters: - node_id (int) – ID to assign this node, to allow consistency with external information.
- kwargs (any, optional) – Additional attributes can be set using keyword arguments. Each key (except node_id) sets an instance variable with the same name.
-
get_id
()¶ Returns the ID of this node.
-
ignore_me
()¶ Sets this node to be treated as temporarily inactive.
Note
After calling this, existing references to this node will remain valid, but any future queries to node_from_id[] will return None. This gives the ability to temporarily ignore nodes without the overhead of deleting them. Provided that we keep an external reference, we can reactivate this node later, using unignore_me() below.
-
unignore_me
()¶ Restore this node to being treated as active.
Note
After calling this, any information about this node (including edges to/from adjancent nodes) that existed before make_invalid() will once again be available.
-
make_edges
(neighbor, label=1)¶ Create edge(s) from this node, with optional weight (default 1).
Parameters: - neighbor (int or list of int) – The ID of the node to connect to.
- label (object or list of objects, optional) – The label/weight information for the edge(s) (default = 1). If a single label is given, all neighbors get that label. If a list is given, it must have the same length as neighbor.
Note
This will overwrite any previous edge to the given neighbor(s). This does not check if neighbor(s) is/are currently active or valid, so we can create edges to node id’s that do not yet exist.
-
remove_edges
(neighbor)¶ Remove any existing edges to the given neighbor(s).
Parameters: neighbor (int or list of int) – The ID of the nodes to remove edges to.
-
neighbor_ids
()¶ The set of IDs of active nodes adjacent to this one.
-
neighbor_nodes
()¶ The set of active nodes adjacent to this one.
-
edges_from
()¶ A dictionary of edges from this node, keyed by neighbor ID. Inactive neighbors are ignored.
Documentation for BOID/Vehicle Code¶
Homegrown BOID-type vehicles and steering behaviours.
BOID/Vehicle Code¶
Two-dimensional Reynolds-style BOIDS and steering behaviours.
vehicle2d.py¶
steering.py¶
Module containing PyBOID steering behavior functions.
Each type of behaviour needs a force_foo() function to compute the actual steering force. The first argument (“owner”) is the vehicle that is being steered. Any number of additional arguments are permitted. This allows the SteeringBehaviour.compute_force functions to automatically call each active behaviour’s force_foo() function with appropriate arguments.
Each behaviour also needs a activate_foo() function. The first argument (“steering”) is an instance of SteeringBehaviour owned by the given vehicle; additional arguments are intended to be stored within the SteeringBehaviour instance and then passed to the corresponding force_foo() each update. See the SEEK code for a simple example.
Many behaviours use constant values, imported from steering_constants.py and assigned to local constants within this module. These are chosen based on the the physics defaults (also in steering_constants) to give reasonable results, but can be overridden with steering.FOO_CONSTANT = new_value. See the sheepdog demo for an example of this.
Importing this module will automatically generate a BEHAVIOUR_LIST containing all behaviours that follow the conventions above. This makes it very easy to add additional behaviours with minimal changes to the existing code (besides writing the force/activate functions, SteeringBehaviour.PRIORITY_LIST would need to be modified with any new behaviours if we use budgeted force).
TODO: set/pause/resume/stop behaviour functions always call set_priorities() regardless of whether budgeted force is actually used. Since we’re currently using budgeted force all the time, this issue is pretty much unimportant.
TODO: Updates to self.flocking are handled through set_priorities(), which is a sensible thing, since set_priorities() is the function that gets called when there is any kind of behaviour change. Make up our minds whether this is truly the right approach and change documentation appropriately.
-
steering.
force_seek
(owner, target)¶ Steering force for SEEK behaviour.
This is a simple behaviour that directs the owner towards a given point. Other, more complex behaviours make use of this.
Parameters: - owner (SimpleVehicle2d) – The vehicle computing this force.
- position (Point2d) – The target point that owner is seeking to.
-
steering.
activate_seek
(steering, target)¶ Activate SEEK behaviour.
-
steering.
force_flee
(owner, target, panic_squared=inf)¶ Steering force for FLEE behaviour.
Another simple behaviour that directs the owner away from a given point.
Parameters: - owner (SimpleVehicle2d) – The vehicle computing this force.
- position (Point2d) – The target point that owner is fleeing from.
- panic_squared (float) – If specified, only compute a flee_force if squared distance to the target is less than this value.
-
steering.
activate_flee
(steering, target)¶ Activate FLEE behaviour.
-
steering.
force_arrive
(owner, target, hesitance=2.0)¶ Steering force for ARRIVE behaviour.
This works like SEEK, except the vehicle gradually deccelerates as it nears the target position. The optional third parameter controls the amount of decceleration.
Parameters: - owner (SimpleVehicle2d) – The vehicle computing this force.
- position (Point2d) – The target point that owner is to arrive at.
- hesistance (float) – Controls the time it takes to deccelerate; higher values give more gradual (and slow) decceleration. Suggested values are 1.0 - 10.0.
-
steering.
activate_arrive
(steering, target)¶ Activate ARRIVE behaviour.
-
steering.
force_pursue
(owner, prey)¶ Steering force for PURSUE behaviour.
Similar to SEEK, but lead the prey by estimating its future location, based on current velocities.
Parameters: - owner (SimpleVehicle2d) – The vehicle computing this force.
- prey (BasePointMass2d) – The vehicle that owner will pursue.
-
steering.
activate_pursue
(steering, prey)¶ Activate PURSUE behaviour.
-
steering.
force_evade
(owner, predator)¶ Steering force for EVADE behaviour.
Similar to FLEE, but try to get away from the predicted future position of the predator. Predators far away are ignored, EVADE_PANIC_SQ is used to control the panic distance passed to FLEE.
Parameters: - owner (SimpleVehicle2d) – The vehicle computing this force.
- predator (BasePointMass2d) – The vehicle that owner will pursue.
-
steering.
activate_evade
(steering, predator)¶ Activate EVADE behaviour.
-
steering.
force_wander
(owner, steering)¶ Steering force for WANDER behavior.
Parameters: - owner (SimpleVehicle2d) – The vehicle computing this force
- steering (SteeringBehavior) – An instance of SteeringBehavior (not a vehicle, see note below)
Note
WANDER requires persistant data (specifically, the target of the wander circle), so we need access to the SteeringBehavior itself instead of the vehicle that owns it.
-
steering.
activate_wander
(steering, target)¶ Activate WANDER behaviour.
-
steering.
force_avoid
(owner, obs_list)¶ Steering force for AVOID stationary obstacles behaviour.
This projects a box in front of the owner and tries to find an obstacle for which collision is imminent (not always the closest obstacle). The owner will attempt to steer around that obstacle.
Parameters: - owner (SimpleVehicle2d) – The vehicle computing this force.
- obs_list (list of BasePointMass2d) – List of obstacles to check for avoidance.
-
steering.
activate_avoid
(steering, target)¶ Activate AVOID behaviour.
-
steering.
force_takecover
(owner, target, obs_list, max_range, stalk=False)¶ Steering force for TAKECOVER behind obstacle.
Owner attempts to move to the nearest position that will put an obstacle between itself and the target. If no such points are within max_range, EVADE the predator instead.
By setting stalk to True, we’ll only hide when in front of the target. Stalking allows this vehicle to (somewhat clumsily) sneak up from behind.
Parameters: - owner (SimpleVehicle2d) – The vehicle computing this force.
- target (BasePointMass2d) – The vehicle we try to hide from.
- obs_list (list of BasePointMass2d) – List of obstacles to check for avoidance.
- max_range (float) – Obstacles further than this value are ignored.
- stalk (boolean) – If True, only hide when we are in front of the target.
-
steering.
activate_takecover
(steering, target)¶ Activate TAKECOVER behaviour.
-
steering.
force_wallavoid
(owner, whisk_units, whisk_lens, wall_list)¶ Steering force for WALLAVOID behaviour with aribtrary whiskers.
For each whisker, we find the wall with point of intersection closest to the base of the whisker. If such a wall is detected, it contributes a force in the direction of the wall normal proportional to the penetration depth of the whisker. Total force is the resultant vector sum.
Parameters: - owner (SimpleVehicle2d) – The vehicle computing this force.
- whisk_units (list of Point2d or 2-tuple) – Whisker UNIT vectors in owner’s local coordinates (forward is x+).
- whisk_lens (list of positive int or float) – Lengths of whiskers, in same order as whisk_units above.
- wall_list (list of BaseWall2d) – Walls to test for avoidance.
-
steering.
activate_wallavoid
(steering, info)¶ Activate WALLAVOID behaviour.
Note
Whisker angles are assumed at 45 degrees; scale is set by steering constants.
-
steering.
force_guard
(owner, guard_this, guard_from, aggro)¶ Steering force for GUARD behavior.
Parameters: - owner (SimpleVehicle2d) – The vehicle computing this force.
- guard_this (BasePointMass2d) – The target that owner is guarding.
- guard_from (BasePointMass2d) – The target that owner is guarding against.
- aggro (float) – Value from 0 to 1; controls aggressiveness (see notes below)
Notes
This is a more general version of INTERPOSE. The vehicle will attempt to position itself between guard_this and guard_from, at a relative distance controlled by aggro. Setting aggro near zero will position near guard_this; aggro near 1.0 will position near guard_from.
The formula is the standard parameterization of a line segment, so we can actually set aggro outside of the unit interval.
-
steering.
activate_guard
(steering, target)¶ Activate GUARD behaviour.
-
steering.
force_follow
(owner, leader, offset)¶ Steering force for FOLLOW the leader at some offset.
Parameters: - owner (SimpleVehicle2d) – The vehicle computing this force.
- leader (BasePointMass2d) – The lead vehicle that the owner is following.
- offset (Point2d) – Offset from leader (in leader’s local coordinates, front = +x)
-
steering.
activate_follow
(steering, target)¶ Activate FOLLOW behaviour.
-
steering.
force_brake
(owner, decay=0.5)¶ Steering force oppoisite of current forward velocity.
Parameters: - owner (SimpleVehicle2d) – The vehicle computing this force.
- decay (float) – Discrete exponential decay constant for speed; 0 < decay < 1.
-
steering.
activate_brake
(steering, target)¶ Activate BRAKE behaviour.
-
class
steering.
WaypointPath
(waypoints, is_cyclic=False)¶ Helper class for managing path-related behaviour, using waypoints.
Parameters: - waypoints (list of Point2d) – Non-empty list of waypoints on this path.
- is_cyclic (boolean) – If set to True, path will automatically cycle. See notes below.
Notes
Instances of WaypointPath should be owned by a SteeringBehaviour, but all path-management code is controlled from within this class.
When using this for vehicle steering, the first waypoint is intended as the starting point of some owner vehicle. The vehicle will not automatically return to this point even if is_cyclic is set to True, so add it manually to the end of waypoints if a return trip is needed.
TODO: It may be helpful to rewrite this class as a generator.
-
reset_from_position
(start_pos, do_return=False)¶ Reset the next waypoint to the start of this path.
Parameters: - start_pos (Point2d) – The new starting point for the path
- do_return (boolean) – If set to True, start_pos becomes the final waypoint. See Notes.
Notes
As with the __init__() method, start_pos is intended as the current location of some vehicle, and is not explicitly added as the first waypoint. If the path was previously cyclic, we will not return to start_pos by default (but the previous waypoints will still continue to cycle). To override this, set do_return=True. However, start_pos will not be added explicitly is it is within the threshold given by PATH_EPSILON_SQ, because it is close enough to an actual waypoint.
-
advance
()¶ Update our waypoint to the next one in the path.
Notes
When we advance() from the last waypoint in a non-cyclic path, the value of self.newway is set to None. This can be used elsewhere??
-
num_left
()¶ Returns the number of waypoints remaining in this path.
Notes
For cyclic paths, we always return the total number of waypoints, regardless of where we are in the list.
-
steering.
force_waypathtraverse
(owner, waypath)¶ Steering force for WAYPATHTRAVERSE behaviour.
Parameters: - owner (SimpleVehicle2d) – The vehicle computing this force.
- waypath (WaypointPath) – Path to be followed by the owner
Notes
This is the simple version; we merely head towards the next waypoint. If there is only one waypoint left, we ARRIVE at it. Otherwise, we SEEK.
-
steering.
activate_waypathtraverse
(steering, waypath)¶ Activate WAYPATHTRAVERSE behaviour.
-
steering.
force_waypathresume
(owner, waypath, invk)¶ Steering force for WAYPATHRESUME behaviour.
Parameters: - owner (SimpleVehicle2d) – The vehicle computing this force.
- waypath (WaypointPath) – Path to be followed by the owner
- invk (positive float) – Reciprocal of exponential decay constant. See Notes.
Notes
If the vehicle is off course, this will give a balance between returning directly to the current path edge and progressing to the next waypoint.
If the vehicle has already overshot the next waypoint, we head directly to that waypoint, ignoring the path. Otherwise, follow an exponential decay curve asymptotic to the path; although this curve doesn’t actually pass through the waypoint, it makes computations very quick, especially since we store invk. Smaller values of invk imply a larger decay rate, and give more immediate return to the path.
-
steering.
activate_waypathresume
(steering, target)¶ Activate WAYPATHRESUME behaviour.
-
steering.
force_flowfollow
(owner, vel_field, dt=1.0)¶ Steering force for FLOWFOLLOW behaviour.
Parameters: - owner (SimpleVehicle2d) – The vehicle computing this force.
- vel_field (function Point2d(Point2d)) – A velocity vector field; owner will attempt to follow this.
- dt (Non-negative float) – Time between steering updates.
-
steering.
activate_flowfollow
(steering, target)¶ Activate FLOWFOLLOW behaviour.
-
steering.
force_separate
(owner)¶ Steering force for SEPARATE group behaviour (flocking).
Parameters: owner (SimpleVehicle2d) – The vehicle computing this force. Notes
Flocking forces use owner.neighbor_list to decide which vehicles to flock with; update this list before calling this function.
For each neighbor, include a force away from that neighbor with magnitude proportional to the neighbor radius and inversely proprotional to distance. This gave nicer results and allows us to cleverly avoid computing a sqrt.
-
steering.
activate_separate
(steering, n_list)¶ Activate SEPARATE behaviour.
-
steering.
force_align
(owner)¶ Steering force for ALIGN group behaviour (flocking).
Parameters: owner (SimpleVehicle2d) – The vehicle computing this force. Notes
Flocking forces use owner.neighbor_list to decide which vehicles to flock with; update this list before calling this function.
Unlike(?) traditional boids, we ALIGN with the average of neighbors’ velocity vectors. Align with heading (normalize velocity) looked weird.
-
steering.
activate_align
(steering, n_list)¶ Activate ALIGN behaviour.
-
steering.
force_cohesion
(owner)¶ Steering force for COHESION group behaviour.
Parameters: owner (SimpleVehicle2d) – The vehicle computing this force. Notes
Flocking forces use owner.neighbor_list to decide which vehicles to flock with; update this list before calling this function.
-
steering.
activate_cohesion
(steering, n_list)¶ Activate COHESION behaviour.
-
steering.
FLOCKING_LIST
= [u'SEPARATE', u'ALIGN', u'COHESION']¶ Flocking behaviours need additional set/pause/resume/stop checking.
-
steering.
force_fnc
(owner, guard_this, guard_from, aggro)¶ Steering force for GUARD behavior.
Parameters: - owner (SimpleVehicle2d) – The vehicle computing this force.
- guard_this (BasePointMass2d) – The target that owner is guarding.
- guard_from (BasePointMass2d) – The target that owner is guarding against.
- aggro (float) – Value from 0 to 1; controls aggressiveness (see notes below)
Notes
This is a more general version of INTERPOSE. The vehicle will attempt to position itself between guard_this and guard_from, at a relative distance controlled by aggro. Setting aggro near zero will position near guard_this; aggro near 1.0 will position near guard_from.
The formula is the standard parameterization of a line segment, so we can actually set aggro outside of the unit interval.
-
steering.
activate_fnc
(steering, target)¶ Activate GUARD behaviour.
-
class
steering.
SteeringBehavior
(vehicle, use_budget=True)¶ Helper class for managing a vehicle’s autonomous steering.
Each vehicle should maintain a reference to an instance of this class, and call the compute_force() method when an update is needed.
Parameters: - vehicle (SimpleVehicle2d) – The vehicle that will be steered by this instance
- use_budget (boolean) – Default (True) uses vehicle’s maxforce as a force budget per update. If set to False, all active behaviors are consdidered each update.
-
set_target
(**kwargs)¶ Initializes one or more steering behaviours.
Parameters: - SEEK ((float, float), optional) – If given, the vehicle will begin SEEKing towards this point.
- FLEE ((float, float), optional) – If given, the vehicle will begin FLEEing towards this point.
- ARRIVE ((float, float), optional) – If given, the vehicle will begin ARRIVEing towards this point.
- PURSUE (BasePointMass2d, optional) – If given, the vehicle will begin PURSUEing the prey.
- EVADE (BasePointMass2d, optional) – If given, the vehicle will begin EVADEing the predator
- TAKECOVER (BasePointMass2d, optional) – If given, the vehicle will try to TAKECOVER from the predator.
- WANDER (tuple of int or float, optional) – (Distance, Radius, Jitter) for WANDER behaviour
- AVOID (tuple of BasePointMass2d, optional) – Tuple (iterable ok?) of obstacles to be avoided.
- WALLAVOID (tuple of BaseWall2d, optional) – List of walls to be avoided
- GUARD ((BasePointMass2d, BasePointMass2d, float), optional) – (GuardTarget, GuardFrom, AggressivePercent)
- WAYPATHTRAVERSE ((WaypointPath), optional) – List of waypoints for WAYPATHTRAVERSE behaviour.
- WAYPATHRESUME ((WaypointPath, invk), optional) – List of waypoints and inverse of decay constant for PATHRESUME.
- FLOWFOLLOW ((vel_field, dt), optional) – Callable vel_field function and time increment
- FOLLOW ((BasePointMass2d, Point2d), optional) – (Leader, OffsetFromLeader)
- SEPARATE (List of BasePointMass2d, optional) – List of targets to flock with
- ALIGN (List of BasePointMass2d, optional) – List of targets to flock with
- COHESION (List of BasePointMass2d, optional) – List of targets to flock with
- BRAKE (float, optional) – Speed decay factor (0 < decay < 1)
Returns: Each item True/False according to whether initialization succeeded.
Return type: list of boolean (or single boolean)
Notes
Flocking behaviours (SEPARATE, ALIGN, COHESION) automatically set self.flocking to True; this is used by force_foo functions so that neighbors need only be tagged once per cycle (for efficiency).
-
pause
(steering_type)¶ Temporarilily turns off a steering behaviour, storing targets for later.
Parameters: steering_type (string) – Name of the behaviour to be paused. Returns: True if the pause was successful, False otherwise. Return type: boolean
-
resume
(steering_type)¶ Turns on a previously paused behaviour, using old targets.
Parameters: steering_type (string) – Name of the behaviour to be resumed. Returns: True if the resume was successful, False otherwise. Return type: boolean
-
stop
(steering_type)¶ Permanently turns off a steering behaviour until re-initialized.
Parameters: steering_type (string) – Name of the behaviour to be stopped. Returns: True if the stop was successful, False otherwise. Return type: boolean
-
update_flocking_status
()¶ Sets or clears flocking status based on currently-active behaviours.
-
flag_neighbor_vehicles
(vehlist=[])¶ Populates a list of nearby vehicles, for use with flocking.
Parameters: vehlist (List of BasePointMass2d) – List of vehicles to be checked against. See Notes below. Notes
This function checks other vehicles based on their distance to owner and includes only vehicles in front of the owner. Maximum distance is the owner’s radius times FLOCKING_RADIUS_MULTIPLIER. We may consider more sophisticated sensing of neighbors in the future.
Any pre-processing (such as spatial partitioning, sensory perception, or flocking with certain vehicles only) should be done before calling this function; with those results passed in as vehlist.
Results of flagging are stored as owner.neighbor_list to be read later by force_foo functions (mostly flocking) that require neighbor information. Run this function before any such force_foo functions).
-
compute_force_simple
()¶ Compute steering force using all currently-active behaviors.
Returns: Point2d Return type: Steering force. Note
This considers all active behaviours, but will still limit the final force vector’s magnitude to the owner’s maxforce.
-
set_priorities
()¶ Create a prioritized list of steering behaviours for later use.
-
compute_force_budgeted
()¶ Find prioritized steering force within the vehicle’s budget.
Returns: Point2d Return type: Steering force.
steering_constants.py¶
Default values of constants for vehicles and steering behaviours.
-
steering_constants.
POINTMASS2D_MASS
= 1.0¶ Vehicle mass for rectilinear motion.
-
steering_constants.
POINTMASS2D_MAXSPEED
= 5.0¶ Maximum vehicle speed per rectilinear motion update.
-
steering_constants.
POINTMASS2D_MAXFORCE
= 3.5¶ Maximum force/budget per rectilinear motion update.
-
steering_constants.
RIGIDBODY2D_INERTIA
= 1.0¶ Rotational Inertia for rigid-body physics
-
steering_constants.
RIGIDBODY2D_MAXOMEGA
= 90.0¶ Maximum angular velocity per rigid-body update.
-
steering_constants.
RIGIDBODY2D_MAXTORQUE
= 75.0¶ Maximum torque per rigid-body update.
-
steering_constants.
FLEE_PANIC_SQ
= inf¶ Used by FLEE; ignore the point if it’s too far away
-
steering_constants.
ARRIVE_DECEL_TWEAK
= 10.0¶ This contols the gradual deceleration for ARRIVE behavior. Larger values will cause more gradual deceleration.
-
steering_constants.
EVADE_PANIC_SQ
= 25600¶ Used by EVADE; we ignore the predator if it is too far away.
-
steering_constants.
AVOID_MIN_LENGTH
= 25¶ This controls the size of an object detection box for AVOID obstacles. Length in front of vehicle is 100%-200% of this.
-
steering_constants.
AVOID_BRAKE_WEIGHT
= 2.0¶ Tweaking constant for braking force of AVOID obstacles.
-
steering_constants.
WALLAVOID_WHISKER_SCALE
= 0.8¶ WALLAVOID – Proportional length of side whiskers relative to front whisker.
-
steering_constants.
TAKECOVER_STALK_T
= 0.1¶ TAKECOVER – For stalking, set this to cos^2(theta), where theta is the max angle from target’s front vector. The stalker will not hide unless within this angle of view.
-
steering_constants.
FOLLOW_ARRIVE_HESITANCE
= 1.5¶ FOLLOW the leader uses ARRIVE with this hesitance, for smooth formations.
-
steering_constants.
PATH_EPSILON_SQ
= 100.0¶ SteeringPath will treat consecutive waypoints that are closer than this as duplicates, and remove them from the path.
-
steering_constants.
WAYPOINT_TOLERANCE_SQ
= 100.0¶ Used by PATHFOLLOW/RESUME to determine when we’re close enough to a waypoint.
-
steering_constants.
PATHRESUME_DECAY
= 0.075¶ Exponential decay constant for PATHRESUME.
-
steering_constants.
FLOCKING_RADIUS_MULTIPLIER
= 2.0¶ For simplicity, we multiply the vehicle’s bounding radius by this constant to determine the local neighborhood radius for group behaviours.
-
steering_constants.
FLOCKING_SEPARATE_SCALE
= 1.2¶ Scaling factor for SEPERATE group behaviour. Larger values give greater seperation force.
-
steering_constants.
FLOCKING_COHESHION_HESITANCE
= 3.5¶ Cohesion uses ARRIVE with this hesitance, for smooth flocking.
-
steering_constants.
BASEPOINTMASS2D_DEFAULTS
= {'MAXSPEED': 5.0, 'MASS': 1.0, 'MAXFORCE': 3.5}¶ Point-Mass physics defaults.
-
steering_constants.
SIMPLERIGIDBODY2D_DEFAULTS
= {'MAXTORQUE': 75.0, 'INERTIA': 1.0, 'MAXOMEGA': 90.0}¶ Additional Rigid Body physics defaults.
-
steering_constants.
STEERING_DEFAULTS
= {'TAKECOVER_STALK_T': 0.1, 'WAYPOINT_TOLERANCE_SQ': 100.0, 'PATH_EPSILON_SQ': 100.0, 'FLOCKING_COHESHION_HESITANCE': 3.5, 'FLOCKING_RADIUS_MULTIPLIER': 2.0, 'EVADE_PANIC_SQ': 25600, 'AVOID_MIN_LENGTH': 25, 'FLOCKING_SEPARATE_SCALE': 1.2, 'PATHRESUME_DECAY': 0.075, 'ARRIVE_DECEL_TWEAK': 10.0, 'FLEE_PANIC_SQ': inf, 'FOLLOW_ARRIVE_HESITANCE': 1.5, 'WALLAVOID_WHISKER_SCALE': 0.8, 'AVOID_BRAKE_WEIGHT': 2.0}¶ Defaults for Steering Behaviours.
Experimentals¶
Ticket price pays for the whole seat, but you’ll only need the edge!
Indices and tables¶
If you need to convince yourself of the awesome power of Sphinx autodocs, look at the (autogenerated) links below: