/** * \param agent * \return The estimated construction time of the device and its components, if the agent is able to buy some components */ double Device::expectedConstructionTime(Agent &agent) { /* * if the agent believes that it can buy the device, the expected time * to build the device is 0. */ if (agent.canBuy(*this).first) { return 0.0; } /* * If the agent does not believe it can buy the device, it calculates * the time required to make the device based on its experience and * whether or not it has a device-making device, then it recursively * adds the expected construction time of each of the components */ device_name_t bestDevDevice = agent.bestDevDevice(type, use); double time; if (bestDevDevice != NO_DEVICE) { time = agent.deviceEffortCalc(use, type) / agent.getDeviceFactor(bestDevDevice); } else { time = agent.deviceEffortCalc(use, type); } for (int i = 0; i < (int) components.size(); i++) { int comp = components[i]; time += glob.discoveredDevices[componentType][comp]->expectedConstructionTime(agent); } return time; }
/** * \param agent * \return the sum of the costs of the components to the agent */ double Device::costs(Agent &agent) { if (agent.devProp[type][use].costOfDeviceMemoryValid) { return agent.devProp[type][use].costOfDeviceMemory; } else { /* canBuy returns a boolean and a double */ pair<bool, double> buy = agent.canBuy(*this); /* * canBuy is the boolean; it indicates whether or not the agent * believes it is able to buy the device */ bool canBuy = buy.first; /* * If the agent believes it is able to buy the device, the price (in * utils) that it expects to pay is avgPrice * So, if the agent believes it is able to buy the device, the cost * is avgPrice. */ double avgPrice = buy.second; if (canBuy) { return avgPrice; /* * If the agent does not believe that it can buy the device, it * calculates the cost of the device as the time required to make * this device plus the cost of all the components of this device * (so the cost function gets called recursively on lower and lower * order devices) */ } else { /* * First the agent calculates the time required to make the * device based on the agent's experience and whether or not it * has a device-making device */ double time; device_name_t bestDevDevice = agent.bestDevDevice(type, use); if (bestDevDevice != NO_DEVICE) { time = agent.deviceEffortCalc(use, type) / agent.getDeviceFactor(bestDevDevice); } else { time = agent.deviceEffortCalc(use, type); } /* * The initial cost is the required time multiplied by the gain * per minute that the agent was getting at the end of the last * work day */ double cost = time * agent.endDayGPM; /* * Then, the agent adds the cost of each of the components of * this device. */ for (int i = 0; i < (int) components.size(); i++) { int comp = components[i]; cost += glob.discoveredDevices[componentType][comp]->costs(agent); } agent.devProp[type][use].costOfDeviceMemory = cost; agent.devProp[type][use].costOfDeviceMemoryValid = true; return cost; } } }
/** * \param an agent * \return a pair of (timeNeeded, necessaryRes) where the necessary time and resources to make the device and its components, if the agent is not able to buy any components. */ pair<double, vector<int> > Device::worstCaseConstruction(Agent &agent) { /* * If the memory of this calculation that the agent has is valid, return * the value in memory */ if (agent.devProp[type][use].worstCaseConstructionMemoryValid) { return agent.devProp[type][use].worstCaseConstructionMemory; } else { /* * highOrderNeeded will be a list of the number of typeToCheck * devices needed for the corresponding resId */ vector<int> highOrderNeeded(glob.NUM_RESOURCES, 0); /* * Begin by requiring one device of the type that is currently under * consideration */ highOrderNeeded[use] = 1; /* typeToCheck begins as the type of device under consideration */ device_name_t typeToCheck = type; /* compType is the component type of typeToCheck */ device_name_t compType = componentType; /* * timeNeeded will be the total, worst case time for this device and * its components. */ double timeNeeded = 0.0; if (devDevice != NO_DEVICE && agent.devProp[devDevice][use].deviceHeld > 0.0) { timeNeeded = agent.deviceEffortCalc(use, type) / agent.getDeviceFactor(devDevice); } else { timeNeeded = agent.deviceEffortCalc(use, type); } /* * Loop through so that typeToCheck and compType become lower and * lower order device types; stop when there are no more lower order * devices to consider. */ while (compType != NO_DEVICE) { /* * Given the number of typeToCheck devices in highOrderNeeded, * compNeeded is the number of compType devices needed for each * corresponding resId. */ vector<int> compNeeded(glob.NUM_RESOURCES, 0); /* * Begin by simply adding the components of devices in * highOrderNeeded */ for (int resId = 0; resId < glob.NUM_RESOURCES; resId++) { if (highOrderNeeded[resId] > 0) { for (int i = 0; i < (int) glob.discoveredDevices[typeToCheck][resId]->components.size(); i++) { int compId = glob.discoveredDevices[typeToCheck][resId]->components[i]; compNeeded[compId] += highOrderNeeded[resId]; } } } for (int resId = 0; resId < glob.NUM_RESOURCES; resId++) { if (compNeeded[resId] > 0) { /* * Remove devices from compNeeded if enough of the * device is held by the agent; the number removed is * the number of devices held (i.e. lifetime held * divided by lifetime per device) */ compNeeded[resId] = max(0, compNeeded[resId] - (int(agent.devProp[compType][resId].deviceHeld) / int(agent.getDeviceLifetime(compType)))); } } /* * The time needed to make each of these components is added to * timeNeeded */ for (int resId = 0; resId < glob.NUM_RESOURCES; resId++) { if (compNeeded[resId] > 0) { device_name_t devDevice = glob.discoveredDevices[compType][resId]->devDevice; /* * If the device-making device is not invented or if * the agent doesn't hold any, the devDeviceFactor * is 1 (i.e. no effect on production) */ double devDeviceFactor = 1.0; if (devDevice != NO_DEVICE && agent.devProp[devDevice][resId].deviceHeld > 0.0) { devDeviceFactor = agent.getDeviceFactor(devDevice); } for (int i = 0; i < compNeeded[resId]; i++) { timeNeeded += agent.tempDeviceEffortCalc(resId, compType, i) / devDeviceFactor; } } } /* * Once held devices have been removed from compNeeded, the * values in highOrderNeeded become the values from compNeeded, * and the loop starts again. */ for (int resId = 0; resId < glob.NUM_RESOURCES; resId++) { highOrderNeeded[resId] = compNeeded[resId]; } // typeToCheck and compType move one order down typeToCheck = compType; compType = glob.discoveredDevices[typeToCheck][use]->componentType; } /* * When compType is None, typeToCheck is 'Tool', so the * highOrderNeeded list is the list of the number of tools needed * for each corresponding resId, so the necessary resources for this * device is the sum of necessary resources for each tool */ vector<int> necessaryRes(glob.NUM_RESOURCES, 0); for (int resIdA = 0; resIdA < glob.NUM_RESOURCES; resIdA++) { if (highOrderNeeded[resIdA] > 0) { vector<int> thisToolNeeds = glob.discoveredDevices[TOOL][resIdA]->necessaryResources; for (int resIdB = 0; resIdB < glob.NUM_RESOURCES; resIdB++) { necessaryRes[resIdB] += highOrderNeeded[resIdA] * thisToolNeeds[resIdB]; } } } // Agents remember this calculated list agent.devProp[type][use].worstCaseConstructionMemory = make_pair(timeNeeded, necessaryRes); agent.devProp[type][use].worstCaseConstructionMemoryValid = true; return pair<double, vector<int> >(timeNeeded, necessaryRes); } }