/**
*
*/
package cz.cuni.mff.abacs.burglar.logics.planning;
import cz.cuni.mff.abacs.burglar.logics.GameMap;
import cz.cuni.mff.abacs.burglar.logics.objects.BaseObject;
import cz.cuni.mff.abacs.burglar.logics.objects.Room;
import cz.cuni.mff.abacs.burglar.logics.objects.agents.Agent;
import cz.cuni.mff.abacs.burglar.logics.objects.agents.BeliefBase;
import cz.cuni.mff.abacs.burglar.logics.objects.agents.Burglar;
import cz.cuni.mff.abacs.burglar.logics.objects.agents.Guard;
import cz.cuni.mff.abacs.burglar.logics.objects.items.Inventory;
import cz.cuni.mff.abacs.burglar.logics.objects.items.Item;
import cz.cuni.mff.abacs.burglar.logics.objects.positions.Camera;
import cz.cuni.mff.abacs.burglar.logics.objects.positions.Door;
import cz.cuni.mff.abacs.burglar.logics.objects.positions.Lockable;
import cz.cuni.mff.abacs.burglar.logics.objects.positions.Position;
import cz.cuni.mff.abacs.burglar.visual.VisualBurglar;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
/**
* Generates PDDL problem files.
*
* Static class.
*
* @author abacs
*
*/
public class PDDLGenerator extends PDDLBase {
// -------------------------------------------------------------------------
// constructors:
protected PDDLGenerator() { }
// -------------------------------------------------------------------------
/**
* Generates a burglar problem.
*
* The burglar object is looked up in the map file.
*
* @param map the environment
* @param roomsToEnter rooms that needs to be included in the path
* @param roomsToAvoid rooms that needs to be avoided in the path
* @param fileName output filename
*/
public static void generateBurglarProblem(
GameMap map,
List<Integer> roomsToEnter,
List<Integer> roomsToAvoid,
String fileName
) {
String problem =
PDDLGenerator.generateBurglarProblem(map, roomsToEnter, roomsToAvoid);
PDDLGenerator.writeToFile(problem, fileName);
if(VisualBurglar.FLAG_SAVE_PLANNING_PROBLEMS){
java.util.Date date = new java.util.Date();
Timestamp tStamp = new Timestamp(date.getTime());
PDDLGenerator.writeToFile(problem, fileName + "." + tStamp + ".pddl");
}
}
/**
* Generates a burglar problem.
*
* @param guard the selected guard to plan for
* @param map the environment
* @param roomsToEnter rooms that needs to be included in the path
* @param roomsToAvoid rooms that needs to be avoided in the path
* @param fileName output filename
*/
public static void generateGuardProblem(
Guard guard,
GameMap map,
List<Integer> roomsToEnter,
List<Integer> roomsToAvoid,
String fileName
) {
String problem =
PDDLGenerator.generateGuardProblem(map, guard, roomsToEnter, roomsToAvoid);
PDDLGenerator.writeToFile(problem, fileName);
if(VisualBurglar.FLAG_SAVE_PLANNING_PROBLEMS){
java.util.Date date = new java.util.Date();
Timestamp tStamp = new Timestamp(date.getTime());
PDDLGenerator.writeToFile(problem, fileName + "." + tStamp + ".pddl");
}
}
// -------------------------------------------------------------------------
/**
* Generates a string for the burglar.
*
* The burglar object is looked up in the map file.
*
* @param map the environment
* @param roomsToEnter rooms that needs to be included in the path
* @param roomsToAvoid rooms that needs to be avoided in the path
* @return string problem
*/
public static String generateBurglarProblem(
GameMap map,
List<Integer> roomsToEnter,
List<Integer> roomsToAvoid
) {
if(VisualBurglar.FLAG_ALL_KNOWING_AGENTS)
return generateAllKnowingAgentProblem(
map, map.getBurglar(),
roomsToEnter, roomsToAvoid
);
else
return generateLimitedKnowledgeAgentProblem(
map, map.getBurglar(),
roomsToEnter, roomsToAvoid
);
}
/**
* Generates a string for the guard.
*
* @param guard the selected guard to plan for
* @param map the environment
* @param roomsToEnter rooms that needs to be included in the path
* @param roomsToAvoid rooms that needs to be avoided in the path
* @return string problem
*/
public static String generateGuardProblem(
GameMap map,
Guard guard,
List<Integer> roomsToEnter,
List<Integer> roomsToAvoid
) {
if(VisualBurglar.FLAG_ALL_KNOWING_AGENTS)
return generateAllKnowingAgentProblem(
map, guard,
roomsToEnter, roomsToAvoid
);
else
return generateLimitedKnowledgeAgentProblem(
map, guard,
roomsToEnter, roomsToAvoid
);
}
// -------------------------------------------------------------------------
/**
* Generates a string for the burglar based on it's beliefs and state.
*
* @param map the environment
* @return string problem
*/
public static String generateDiscoveringBurglarProblem(GameMap map) {
StringBuilder builder = new StringBuilder();
Burglar burglar = map.getBurglar();
// generate the header:
builder.append("(define (problem burglar)\n");
builder.append("\t(:domain burglar)\n");
// ----------------------------
// list the objects:
builder.append(STR_TAG_OBJECTS);
// sort positions by type:
List<Position> positions = burglar.getBeliefBase().getKnownPositions();
String strPositions = PDDLGenerator.generatePositionList(positions, true);
builder.append(strPositions);
// rooms:
List<Room> rooms = map.getRooms();
String strRooms = PDDLGenerator.generateRoomList(rooms);
builder.append(strRooms);
// items:
List<Item> items = map.getItems();
String strItems = PDDLGenerator.generateItemList(items);
builder.append(strItems);
// agents:
List<Agent> agents = new ArrayList<Agent>();
agents.add(burglar);
String strAgents = PDDLGenerator.generateAgentList(agents);
builder.append(strAgents);
builder.append(STR_TAG_END);
// ----------------------------
// init:
builder.append(STR_TAG_INIT);
// init position details:
for(Position pos : positions){
if(pos.isTypeOf(BaseObject.Type.DOOR)){
String posName = generateObjectName(pos);
if(((Lockable)pos).isClosed())
generateInlineTag(builder, STR_TAG_CLOSED, posName);
if(((Lockable)pos).isLocked())
generateInlineTag(builder, STR_TAG_LOCKED, posName);
if(((Lockable)pos).getKeyId() > 0){
generateInlineTag(
builder,
STR_TAG_NEEDS_KEY,
posName,
generateObjectName(((Lockable)pos).getKeyId())
);
}
Room[] connectedRooms = ((Door)pos).getRooms();
generateInlineTag(
builder,
STR_TAG_DOOR_CONNECTS,
posName,
generateObjectName(connectedRooms[0]),
generateObjectName(connectedRooms[1])
);
generateInlineTag(
builder,
STR_TAG_DOOR_CONNECTS,
posName,
generateObjectName(connectedRooms[1]),
generateObjectName(connectedRooms[0])
);
generateInlineTag(
builder,
STR_TAG_POSITION_IN,
posName,
generateObjectName(connectedRooms[0])
);
generateInlineTag(
builder,
STR_TAG_POSITION_IN,
posName,
generateObjectName(connectedRooms[1])
);
}
}
// init agent:
generateInlineTag(
builder,
STR_TAG_AGENT_NEAR,
generateObjectName(burglar),
generateDummyName(STR_TYPE_FLOOR)
);
generateInlineTag(
builder,
STR_TAG_POSITION_IN,
generateDummyName(STR_TYPE_FLOOR),
generateObjectName(burglar.getRoom())
);
generateInlineTag(
builder,
STR_TAG_AGENT_IN,
generateObjectName(burglar),
generateObjectName(burglar.getRoom())
);
generateInlineTag(
builder,
STR_TAG_VISITED,
generateObjectName(burglar),
generateObjectName(burglar.getRoom())
);
for(Item item : burglar.getItems()){
generateInlineTag(
builder,
STR_TAG_CONTAINS,
generateObjectName(burglar),
generateObjectName(item)
);
}
// finish init:
builder.append(STR_TAG_END);
// ----------------------------
// define goal:
builder.append("\t(:goal\n\t\t(and\n");
generateInlineTag(
builder,
'\t' + STR_TAG_AGENT_IN,
generateObjectName(burglar),
generateObjectName(burglar.getAimId())
);
generateInlineTag(
builder,
'\t' + STR_TAG_CONTAINS,
generateObjectName(burglar),
generateObjectName(burglar.getItemIdToCollect())
);
builder.append("\t\t)\n\t)\n");
// finish:
builder.append(STR_TAG_END_);
return builder.toString();
}
/**
* Generates a string for the agent based on the full knowledge of the map.
*
* @param agent the selected agent
* @param map the environment
* @param roomsToEnter rooms that needs to be included in the path
* @param roomsToAvoid rooms that needs to be avoided in the path
* @return string problem
*/
public static String generateLimitedKnowledgeAgentProblem(
GameMap map,
Agent agent,
List<Integer> roomsToEnter,
List<Integer> roomsToAvoid
) {
BeliefBase belief = agent.getBeliefBase();
// sort positions by type:
List<Position> positions = belief.getKnownPositions();
// rooms:
List<Integer> rooms = map.getRoomIds();
// items:
List<Item> items = map.getItems();
// TODO
// passive agents:
List<Agent> passiveAgents = belief.getPassiveAgents();
return generateAgentProblem(
positions,
rooms,
items,
passiveAgents,
agent,
roomsToEnter,
roomsToAvoid
);
}
/**
* Generates a string for the agent based on the full knowledge of the map.
*
* @param agent the selected agent
* @param map the environment
* @param roomsToEnter rooms that needs to be included in the path
* @param roomsToAvoid rooms that needs to be avoided in the path
* @return string problem
*/
public static String generateAllKnowingAgentProblem(
GameMap map,
Agent agent,
List<Integer> roomsToEnter,
List<Integer> roomsToAvoid
) {
// positions:
List<Position> positions = map.getOperablePositions();
// rooms:
List<Integer> rooms = map.getRoomIds();
// items:
List<Item> items = map.getItems();
// passive agents:
List<Agent> passiveAgents = map.getPassiveAgents();
return generateAgentProblem(
positions,
rooms,
items,
passiveAgents,
agent,
roomsToEnter,
roomsToAvoid
);
}
// -------------------------------------------------------------------------
/**
* Generates a string for the agent based on the knowledge given
* in the parameters.
*
* @param knownPositions list of known positions
* @param knownRooms list of rooms
* @param knownItems items on the map
* @param passiveAgents other agents on the map
* @param agent the selected agent
* @param roomsToEnter rooms that needs to be included in the path
* @param roomsToAvoid rooms that needs to be avoided in the path
* @return string problem
*/
public static String generateAgentProblem(
List<Position> knownPositions,
List<Integer> knownRooms,
List<Item> knownItems,
List<Agent> passiveAgents,
Agent agent,
List<Integer> roomsToEnter,
List<Integer> roomsToAvoid
) {
StringBuilder builder = new StringBuilder();
// generate the header section:
builder.append("(define (problem agent)\n");
builder.append("\t(:domain agent)\n");
// ----------------------------
// list the objects:
builder.append(STR_TAG_OBJECTS);
// add the current position to the position list only if it's an unimportant one,
// otherwise it should be there
if(agent.getPosition().isOperable() == false){
knownPositions.add(agent.getPosition());
}
// sort positions by type:
String strPositions = PDDLGenerator.generatePositionList(knownPositions, true);
builder.append(strPositions);
// rooms:
String strRooms = PDDLGenerator.generateRoomListFromIds(knownRooms);
builder.append(strRooms);
// items:
String strItems = PDDLGenerator.generateItemList(knownItems);
builder.append(strItems);
// passive agents:
String strPassiveAgents = PDDLGenerator.generatePassiveAgentList(passiveAgents);
builder.append(strPassiveAgents);
// the agent:
List<Agent> agents = new LinkedList<Agent>();
agents.add(agent);
String strAgents = PDDLGenerator.generateAgentList(agents);
builder.append(strAgents);
builder.append(STR_TAG_END);
// ----------------------------
// generate the init sections:
builder.append(STR_TAG_INIT);
// init position details:
for(Position pos : knownPositions){
String posName = generateObjectName(pos);
// location:
if(pos.isTypeOf(BaseObject.Type.DOOR) == false){
generateInlineTag(
builder,
STR_TAG_POSITION_IN,
posName,
generateObjectName(pos.getRoomId())
);
}
// set type:
switch(pos.getType()){
case CONTAINER:
if(((Lockable)pos).isClosed())
generateInlineTag(builder, STR_TAG_CLOSED, posName);
if(((Lockable)pos).isLocked())
generateInlineTag(builder, STR_TAG_LOCKED, posName);
if(((Lockable)pos).getKeyId() > 0){
generateInlineTag(
builder,
STR_TAG_NEEDS_KEY,
posName,
generateObjectName(((Lockable)pos).getKeyId())
);
}
for(Item item : ((Inventory)pos).getItems()){
generateInlineTag(
builder,
STR_TAG_CONTAINS,
posName,
generateObjectName(item)
);
}
break;
case DOOR:
if(((Lockable)pos).isClosed())
generateInlineTag(builder, STR_TAG_CLOSED, posName);
if(((Lockable)pos).isLocked())
generateInlineTag(builder, STR_TAG_LOCKED, posName);
if(((Lockable)pos).getKeyId() > 0){
generateInlineTag(
builder,
STR_TAG_NEEDS_KEY,
posName,
generateObjectName(((Lockable)pos).getKeyId())
);
}
int[] connectedRooms = ((Door)pos).getRoomIds();
generateInlineTag(
builder,
STR_TAG_DOOR_CONNECTS,
posName,
generateObjectName(connectedRooms[0]),
generateObjectName(connectedRooms[1])
);
generateInlineTag(
builder,
STR_TAG_DOOR_CONNECTS,
posName,
generateObjectName(connectedRooms[1]),
generateObjectName(connectedRooms[0])
);
generateInlineTag(
builder,
STR_TAG_POSITION_IN,
posName,
generateObjectName(connectedRooms[0])
);
generateInlineTag(
builder,
STR_TAG_POSITION_IN,
posName,
generateObjectName(connectedRooms[1])
);
break;
case FLOOR:
// not an important position
break;
case VENDER:
// TODO
break;
case CAMERA:
if(((Camera)pos).isActive()){
generateInlineTag(
builder,
STR_TAG_ROOM_OBSERVED,
generateObjectName(pos.getRoomId())
);
}
break;
}
}
// the passive agents:
for(Agent passiveAgent : passiveAgents){
String posName = generateObjectName(passiveAgent.getId());
// location:
generateInlineTag(
builder,
STR_TAG_POSITION_IN,
posName,
generateObjectName(passiveAgent.getRoomId())
);
}
// agent init:
generateInlineTag(
builder,
STR_TAG_AGENT_NEAR,
generateObjectName(agent.getId()),
generateObjectName(agent.getPositionId())
);
generateInlineTag(
builder,
STR_TAG_POSITION_IN,
generateObjectName(agent.getPositionId()),
generateObjectName(agent.getRoomId())
);
generateInlineTag(
builder,
STR_TAG_AGENT_IN,
generateObjectName(agent.getId()),
generateObjectName(agent.getRoomId())
);
for(Item item : agent.getItems()){
generateInlineTag(
builder,
STR_TAG_CONTAINS,
generateObjectName(agent.getId()),
generateObjectName(item)
);
}
builder.append(generateTypeSpecificInit(agent));
// finish init:
builder.append(STR_TAG_END);
// ----------------------------
// define goal:
builder.append("\t(:goal\n\t\t(and\n");
builder.append(generateTypeSpecificGoals(agent));
// require entering rooms if needed:
for(Integer room : roomsToEnter){
generateInlineTag(
builder,
'\t' + STR_TAG_VISITED,
generateObjectName(agent.getId()),
generateObjectName(room)
);
}
// require avoiding rooms if needed:
for(Integer room : roomsToAvoid){
builder.append("\t\t");
builder.append(STR_TAG_NOT);
builder.append(STR_TAG_VISITED);
builder.append(generateObjectName(agent.getId()));
builder.append(' ');
builder.append(generateObjectName(room));
builder.append(STR_TAG_END__);
builder.append(STR_TAG_END_);
}
builder.append("\t\t)\n\t)\n");
// finish:
builder.append(STR_TAG_END_);
return builder.toString();
}
private static String generateTypeSpecificGoals(Agent agent) {
StringBuilder builder = new StringBuilder();
if(agent.getGoals().hasVenderToVisit()){
generateInlineTag(
builder,
'\t' + STR_TAG_POSITION_USED,
generateObjectName(agent.getId()),
generateObjectName(agent.getGoals().getVenderIdToVisit())
);
}else{
switch(agent.getType()){
case BURGLAR:
Burglar burglar = (Burglar)agent;
generateInlineTag(
builder,
'\t' + STR_TAG_AGENT_IN,
generateObjectName(burglar.getId()),
generateObjectName(burglar.getAimId())
);
generateInlineTag(
builder,
'\t' + STR_TAG_CONTAINS,
generateObjectName(burglar),
generateObjectName(burglar.getItemIdToCollect())
);
builder.append("\t\t");
builder.append(STR_TAG_NOT);
builder.append(STR_TAG_OBSERVED);
builder.append(generateObjectName(agent.getId()));
builder.append(STR_TAG_END__);
builder.append(STR_TAG_END_);
break;
case GUARD:
Guard guard = (Guard) agent;
for(Integer room : guard.getAllGoalRooms()){
generateInlineTag(
builder,
'\t' + STR_TAG_VISITED,
generateObjectName(agent.getId()),
generateObjectName(room)
);
if(guard.getRoomId() == room){
generateInlineTag(
builder,
'\t' + STR_TAG_AGENT_IN,
generateObjectName(agent.getId()),
generateObjectName(room)
);
}
}
break;
}
}
return builder.toString();
}
private static String generateTypeSpecificInit(Agent agent) {
StringBuilder builder = new StringBuilder();
switch(agent.getType()){
case BURGLAR:
break;
case GUARD:
break;
}
return builder.toString();
}
// -------------------------------------------------------------------------
private static void generateInlineTag(
StringBuilder builder,
String tagName,
String param
) {
builder.append(tagName);
builder.append(param);
builder.append(STR_TAG_END_);
}
private static void generateInlineTag(
StringBuilder builder,
String tagName,
String param1,
String param2
) {
builder.append(tagName);
builder.append(param1);
builder.append(' ');
builder.append(param2);
builder.append(STR_TAG_END_);
}
private static void generateInlineTag(
StringBuilder builder,
String tagName,
String param1,
String param2,
String param3
) {
builder.append(tagName);
builder.append(param1);
builder.append(' ');
builder.append(param2);
builder.append(' ');
builder.append(param3);
builder.append(STR_TAG_END_);
}
}