| … | … | @@ -8,6 +8,7 @@ import json |
| 8 | 8 | import math |
| 9 | 9 | import signal |
| 10 | 10 | from contextlib import contextmanager |
| 11 | import random |
| 11 | 12 | |
| 12 | 13 | |
| 13 | 14 | @contextmanager |
| … | … | @@ -97,6 +98,23 @@ def drawLine(x1, y1, z1, x2, y2, z2, blocktype, face): |
| 97 | 98 | ) |
| 98 | 99 | |
| 99 | 100 | |
| 101 | def draw_fence(x, y, z): |
| 102 | fence = "" |
| 103 | xy_coord = [(-x, z), (x, z), (x, -z), (-x, -z)] |
| 104 | for i in range(4): |
| 105 | fence += drawLine( |
| 106 | x1=xy_coord[i][0], |
| 107 | y1=y, |
| 108 | z1=xy_coord[i][1], |
| 109 | x2=xy_coord[i + 1][0] if i < 3 else xy_coord[0][0], |
| 110 | y2=y, |
| 111 | z2=xy_coord[i + 1][1] if i < 3 else xy_coord[0][1], |
| 112 | blocktype="fence", |
| 113 | face="WEST", |
| 114 | ) |
| 115 | return fence |
| 116 | |
| 117 | |
| 100 | 118 | def build_house(x, y, z, width, length, height, blocktype): |
| 101 | 119 | x_front = x |
| 102 | 120 | x_back = x + length if x >= 0 else x - length |
| … | … | @@ -114,7 +132,7 @@ def build_house(x, y, z, width, length, height, blocktype): |
| 114 | 132 | if j > 0 and j < width: |
| 115 | 133 | genstring = ( |
| 116 | 134 | genstring |
| 117 | | + drawBlock(x_back + 1, y_cur, z_cur, "diamond_block") |
| 135 | + drawBlock(x_back + 1, y_cur, z_cur, "diamond_ore") |
| 118 | 136 | + "\n" |
| 119 | 137 | ) |
| 120 | 138 | z_cur = z_cur + 1 if z_cur >= 0 else z_cur - 1 |
| … | … | @@ -142,7 +160,7 @@ def build_house(x, y, z, width, length, height, blocktype): |
| 142 | 160 | 15, |
| 143 | 161 | y, |
| 144 | 162 | -15, |
| 145 | | blocktype, |
| 163 | "obsidian", |
| 146 | 164 | ) |
| 147 | 165 | # ceiling |
| 148 | 166 | genstring = genstring + GenCuboid( |
| … | … | @@ -207,21 +225,47 @@ def build_house(x, y, z, width, length, height, blocktype): |
| 207 | 225 | agent_x, agent_y, agent_z, agent_yaw = 13, 230, -2, 90 |
| 208 | 226 | key_x, key_y, key_z = 7, 228, -10 |
| 209 | 227 | door_x, door_y, door_z = -4, 228, -3 |
| 228 | exit_x, exit_y, exit_z = -9, 228, -1 |
| 210 | 229 | diamond_x, diamond_y, diamond_z = -18, 228, -3 |
| 211 | | start_x, start_y, start_z, width, length, height = -4, 226, -1, 6, 9, 3 |
| 230 | start_x, start_y, start_z, width, length, height = -4, 226, -1, 6, 9, 4 |
| 212 | 231 | hold_key = False |
| 232 | fence_max = 15 |
| 233 | |
| 234 | place_count = 0 |
| 235 | pitch_adjusted = False |
| 236 | total_reward = 0 |
| 237 | |
| 238 | |
| 239 | def adjust_pitch(agent): |
| 240 | global pitch_adjusted |
| 241 | if not pitch_adjusted: |
| 242 | agent.sendCommand("pitch 0.5") |
| 243 | time.sleep(0.5) |
| 244 | agent.sendCommand("pitch 0") |
| 245 | pitch_adjusted = True |
| 246 | |
| 213 | 247 | |
| 214 | 248 | # relocates the agent to the starting point |
| 215 | | def relocate_agent(agent): |
| 216 | | print("Agent relocated to original place") |
| 249 | def relocate_agent(agent, msg=""): |
| 250 | print(msg) |
| 217 | 251 | agent.sendCommand("tp {} {} {}".format(agent_x, agent_y, agent_z)) |
| 252 | if not hold_key: |
| 253 | agent.sendCommand("hotbar.4 1") |
| 218 | 254 | agent.sendCommand("setYaw {}".format(agent_yaw)) |
| 219 | 255 | time.sleep(0.2) |
| 220 | 256 | |
| 221 | 257 | |
| 258 | blocks = { |
| 259 | "gold_block": "key", |
| 260 | "dark_oak_door": "house", |
| 261 | "diamond_block": "diamonds", |
| 262 | "planks": "planks", |
| 263 | "diamond_ore": "diamonds", |
| 264 | } |
| 265 | |
| 222 | 266 | # stop the agent |
| 223 | 267 | def stop_condition(agent, blocktype, sec=10): |
| 224 | | print("Moving to the {}".format(blocktype)) |
| 268 | print("Moving to the {}".format(blocks[blocktype])) |
| 225 | 269 | |
| 226 | 270 | def stop(agent, blocktype): |
| 227 | 271 | done = False |
| … | … | @@ -239,9 +283,8 @@ def stop_condition(agent, blocktype, sec=10): |
| 239 | 283 | stop(agent, blocktype) |
| 240 | 284 | return True |
| 241 | 285 | except TimeoutError: |
| 242 | | print("*********** Time out **************") |
| 243 | 286 | agent.sendCommand("move 0") |
| 244 | | relocate_agent(agent) |
| 287 | relocate_agent(agent, msg="*** RELOCATE: Unable to reach the target ***") |
| 245 | 288 | return False |
| 246 | 289 | |
| 247 | 290 | |
| … | … | @@ -253,13 +296,14 @@ def get_curr_loc(agent): |
| 253 | 296 | world_state = agent.peekWorldState() |
| 254 | 297 | if world_state.number_of_observations_since_last_state > 0: |
| 255 | 298 | ob = json.loads(world_state.observations[-1].text) |
| 256 | | loc = (int(ob[u"XPos"]), int(ob[u"YPos"]), int(ob[u"ZPos"])) |
| 299 | yaw = int(ob["Yaw"]) |
| 300 | loc = (int(ob[u"XPos"]), int(ob[u"YPos"]), int(ob[u"ZPos"]), yaw) |
| 257 | 301 | break |
| 258 | 302 | return loc |
| 259 | 303 | |
| 260 | 304 | |
| 261 | 305 | # Turns the agent towards the location given |
| 262 | | def turn_to(agent, x1, y1, z1, x2, y2, z2): |
| 306 | def turn_to(agent, x1, y1, z1, x2, y2, z2, curr_yaw=False): |
| 263 | 307 | def get_angle(x1, y1, z1, x2, y2, z2): |
| 264 | 308 | x_dist = abs(x1 - x2) |
| 265 | 309 | z_dist = abs(z1 - z2) |
| … | … | @@ -272,7 +316,22 @@ def turn_to(agent, x1, y1, z1, x2, y2, z2): |
| 272 | 316 | angle = yaw - angle if z1 < z2 else yaw + angle |
| 273 | 317 | else: |
| 274 | 318 | angle = yaw + angle if z1 < z2 else yaw - angle |
| 275 | | agent.sendCommand("setYaw {}".format(angle)) |
| 319 | if curr_yaw: |
| 320 | if curr_yaw < angle: |
| 321 | agent.sendCommand("turn 0.5") |
| 322 | else: |
| 323 | agent.sendCommand("turn -0.5") |
| 324 | while is_mission_running: |
| 325 | world_state = agent.peekWorldState() |
| 326 | if world_state.number_of_observations_since_last_state > 0: |
| 327 | ob = json.loads(world_state.observations[-1].text) |
| 328 | yaw = int(ob["Yaw"]) |
| 329 | if abs(yaw - angle) < 5: |
| 330 | agent.sendCommand("turn 0") |
| 331 | agent.sendCommand("setYaw {}".format(angle)) |
| 332 | break |
| 333 | else: |
| 334 | agent.sendCommand("setYaw {}".format(angle)) |
| 276 | 335 | |
| 277 | 336 | |
| 278 | 337 | def is_mission_running(agent): |
| … | … | @@ -301,48 +360,50 @@ def get_txt(obs): |
| 301 | 360 | # Move the agent towards the key |
| 302 | 361 | # reward=0 |
| 303 | 362 | def go_to_key(agent): |
| 304 | | agent.sendCommand("chat Grab key") |
| 363 | adjust_pitch(agent) |
| 305 | 364 | global hold_key |
| 306 | 365 | reward = 0 |
| 307 | 366 | observation = {} |
| 308 | | curr_x, curr_y, curr_z = get_curr_loc(agent) |
| 367 | curr_x, curr_y, curr_z, curr_yaw = get_curr_loc(agent) |
| 309 | 368 | if inside_house(curr_x, curr_z): |
| 310 | 369 | observation["inside"] = ["self", "house"] |
| 311 | | agent.sendCommand("chat => {}".format(get_txt(observation))) |
| 370 | print("Observation => {}".format(get_txt(observation))) |
| 312 | 371 | return observation, reward, is_mission_running |
| 313 | 372 | else: |
| 314 | 373 | observation["outside"] = ["self", "house"] |
| 315 | 374 | if hold_key: |
| 316 | 375 | observation["hold"] = ["self", "key"] |
| 317 | | agent.sendCommand("chat => {}".format(get_txt(observation))) |
| 376 | print("Observation => {}".format(get_txt(observation))) |
| 318 | 377 | return observation, reward, is_mission_running |
| 319 | | turn_to(agent, curr_x, curr_y, curr_z, key_x, key_y, key_z) |
| 378 | turn_to(agent, curr_x, curr_y, curr_z, key_x, key_y, key_z, curr_yaw=curr_yaw) |
| 320 | 379 | time.sleep(0.2) |
| 321 | 380 | agent.sendCommand("move 1") |
| 322 | | action_complete = stop_condition(agent, "tripwire_hook") |
| 381 | action_complete = stop_condition(agent, "gold_block") |
| 323 | 382 | if action_complete: |
| 324 | 383 | observation["hold"] = ["self", "key"] |
| 325 | 384 | agent.sendCommand("hotbar.2 1") |
| 326 | 385 | hold_key = True |
| 327 | 386 | else: |
| 328 | 387 | observation = [] |
| 329 | | agent.sendCommand("chat => {}".format(get_txt(observation))) |
| 388 | print("Observation => {}".format(get_txt(observation))) |
| 330 | 389 | return observation, reward, is_mission_running |
| 331 | 390 | |
| 332 | 391 | |
| 333 | 392 | # Move the agent towards the house and enter the house. |
| 334 | 393 | # reward = 0 |
| 335 | 394 | def go_to_house(agent): |
| 336 | | agent.sendCommand("chat Open door") |
| 395 | adjust_pitch(agent) |
| 337 | 396 | global hold_key |
| 338 | 397 | reward = 0 |
| 339 | 398 | observation = {} |
| 340 | | curr_x, curr_y, curr_z = get_curr_loc(agent) |
| 399 | curr_x, curr_y, curr_z, curr_yaw = get_curr_loc(agent) |
| 341 | 400 | if inside_house(curr_x, curr_z): |
| 342 | 401 | observation["inside"] = ["self", "house"] |
| 343 | | agent.sendCommand("chat => {}".format(get_txt(observation))) |
| 402 | print("Observation => {}".format(get_txt(observation))) |
| 344 | 403 | return observation, reward, is_mission_running |
| 345 | | turn_to(agent, curr_x, curr_y, curr_z, door_x + 2, door_y, door_z) |
| 404 | turn_to( |
| 405 | agent, curr_x, curr_y, curr_z, door_x + 2, door_y, door_z, curr_yaw=curr_yaw |
| 406 | ) |
| 346 | 407 | time.sleep(0.2) |
| 347 | 408 | agent.sendCommand("move 1") |
| 348 | 409 | action_complete = stop_condition(agent, "dark_oak_door") |
| … | … | @@ -350,7 +411,7 @@ def go_to_house(agent): |
| 350 | 411 | if hold_key: |
| 351 | 412 | time.sleep(0.2) |
| 352 | 413 | agent.sendCommand("tp {} {} {}".format(door_x, door_y, door_z)) |
| 353 | | time.sleep(0.2) |
| 414 | time.sleep(0.1) |
| 354 | 415 | observation["inside"] = ["self", "house"] |
| 355 | 416 | agent.sendCommand("hotbar.1 1") |
| 356 | 417 | hold_key = False |
| … | … | @@ -358,27 +419,100 @@ def go_to_house(agent): |
| 358 | 419 | observation["outside"] = ["self", "house"] |
| 359 | 420 | observation["nextto"] = ["self", "closed_door"] |
| 360 | 421 | reward = 0 |
| 361 | | agent.sendCommand("chat => {}".format(get_txt(observation))) |
| 422 | print("Observation => {}".format(get_txt(observation))) |
| 362 | 423 | return observation, reward, is_mission_running |
| 363 | 424 | |
| 364 | 425 | |
| 426 | def place_diamonds(agent): |
| 427 | global place_count |
| 428 | curr_x, curr_y, curr_z, curr_yaw = get_curr_loc(agent) |
| 429 | turn_to( |
| 430 | agent, |
| 431 | curr_x, |
| 432 | curr_y, |
| 433 | curr_z, |
| 434 | (exit_x + 2) + (2 * place_count), |
| 435 | exit_y, |
| 436 | fence_max, |
| 437 | ) |
| 438 | agent.sendCommand("move 1") |
| 439 | time.sleep(2 - (place_count * 0.01)) |
| 440 | placed = False |
| 441 | while not placed: |
| 442 | world_state = agent.getWorldState() |
| 443 | if world_state.number_of_observations_since_last_state > 0: |
| 444 | msg = world_state.observations[-1].text |
| 445 | ob = json.loads(msg) |
| 446 | # Use the line-of-sight observation to determine where to place: |
| 447 | if u"LineOfSight" in ob: |
| 448 | agent.sendCommand("turn {}".format(random.choice([0.05, -0.05]))) |
| 449 | los = ob[u"LineOfSight"] |
| 450 | x = int(math.floor(los["x"])) |
| 451 | z = int(math.floor(los["z"])) |
| 452 | if los["inRange"]: |
| 453 | agent.sendCommand("move 0") |
| 454 | time.sleep(2) |
| 455 | agent.sendCommand("use") |
| 456 | agent.sendCommand("turn 0") |
| 457 | agent.sendCommand("hotbar.5 1") |
| 458 | time.sleep(2) |
| 459 | place_count += 1 |
| 460 | placed = True |
| 461 | |
| 462 | |
| 463 | def exit(agent): |
| 464 | curr_x, curr_y, curr_z, curr_yaw = get_curr_loc(agent) |
| 465 | turn_to(agent, curr_x, curr_y, curr_z, exit_x, exit_y, exit_z) |
| 466 | agent.sendCommand("move 1") |
| 467 | agent.sendCommand("use 1") |
| 468 | time.sleep(0.2) |
| 469 | while is_mission_running(agent): |
| 470 | curr_x, curr_y, curr_z, _ = get_curr_loc(agent) |
| 471 | if not inside_house(curr_x, curr_z): |
| 472 | agent.sendCommand("move 0") |
| 473 | agent.sendCommand("tp {} {} {}".format(exit_x + 0.5, curr_y, exit_z + 1)) |
| 474 | time.sleep(0.1) |
| 475 | curr_x, curr_y, curr_z, _ = get_curr_loc(agent) |
| 476 | turn_to(agent, curr_x, curr_y, curr_z, exit_x, exit_y, exit_z) |
| 477 | agent.sendCommand("use 1") |
| 478 | time.sleep(0.05) |
| 479 | agent.sendCommand("use 0") |
| 480 | break |
| 481 | agent.sendCommand("hotbar.3 1") |
| 482 | place_diamonds(agent) |
| 483 | |
| 484 | |
| 365 | 485 | # Move the agent towards the diamond and collect it. |
| 366 | 486 | # reward = 1 |
| 367 | 487 | def go_to_diamonds(agent): |
| 368 | | agent.sendCommand("chat Collect diamonds") |
| 488 | global total_reward |
| 489 | adjust_pitch(agent) |
| 490 | # agent.sendCommand("chat Collect diamonds") |
| 369 | 491 | observation = {} |
| 370 | | curr_x, curr_y, curr_z = get_curr_loc(agent) |
| 371 | | turn_to(agent, curr_x, curr_y, curr_z, diamond_x, diamond_y, diamond_z) |
| 492 | curr_x, curr_y, curr_z, curr_yaw = get_curr_loc(agent) |
| 493 | turn_to( |
| 494 | agent, |
| 495 | curr_x, |
| 496 | curr_y, |
| 497 | curr_z, |
| 498 | diamond_x, |
| 499 | diamond_y, |
| 500 | diamond_z, |
| 501 | curr_yaw=curr_yaw, |
| 502 | ) |
| 372 | 503 | time.sleep(0.2) |
| 373 | 504 | agent.sendCommand("move 1") |
| 374 | | action_complete = stop_condition(agent, "diamond_block") |
| 505 | action_complete = stop_condition(agent, "diamond_ore") |
| 375 | 506 | if action_complete: |
| 376 | 507 | agent.sendCommand("attack 1") |
| 377 | 508 | time.sleep(0.2) |
| 378 | 509 | agent.sendCommand("attack 0") |
| 379 | 510 | time.sleep(0.2) |
| 380 | 511 | reward = 1 |
| 512 | total_reward += 1 |
| 513 | exit(agent) |
| 381 | 514 | relocate_agent(agent) |
| 515 | time.sleep(0.3) |
| 382 | 516 | observation["outside"] = ["self", "house"] |
| 383 | 517 | else: |
| 384 | 518 | reward = 0 |
| … | … | @@ -387,9 +521,13 @@ def go_to_diamonds(agent): |
| 387 | 521 | if hold_key: |
| 388 | 522 | observation["hold"] = ["self", "key"] |
| 389 | 523 | if reward > 0: |
| 390 | | agent.sendCommand("chat => Reward {}".format(reward)) |
| 524 | agent.sendCommand("chat Reward = {}".format(reward)) |
| 525 | agent.sendCommand("chat => Total Reward of {} diamonds!".format(total_reward)) |
| 526 | print("Reward = {}".format(reward)) |
| 527 | print("Total Reward of {} diamonds!".format(total_reward)) |
| 528 | |
| 391 | 529 | else: |
| 392 | | agent.sendCommand("chat => {}".format(get_txt(observation))) |
| 530 | print("Observation => {}".format(get_txt(observation))) |
| 393 | 531 | |
| 394 | 532 | return observation, reward, is_mission_running |
| 395 | 533 | |
| … | … | @@ -414,16 +552,22 @@ missionXML = ( |
| 414 | 552 | <AllowSpawning>true</AllowSpawning> |
| 415 | 553 | </ServerInitialConditions> |
| 416 | 554 | <ServerHandlers> |
| 417 | | <FlatWorldGenerator generatorString="3;7,220*1,5*3,2;1;biome_1"/> |
| 555 | <FlatWorldGenerator generatorString="3;7,220*1,5*3,2;1;village,decoration"/> |
| 418 | 556 | <DrawingDecorator> |
| 419 | 557 | """ |
| 420 | 558 | + build_house(start_x, start_y, start_z, width, length, height, "brick_block") |
| 559 | + drawBlock(diamond_x + 5, diamond_y, diamond_z - 1, "diamond_block") |
| 421 | 560 | + drawBlock( |
| 422 | 561 | door_x, door_y - 1, door_z, "dark_oak_door", variant="lower", face="WEST" |
| 423 | 562 | ) |
| 424 | 563 | + drawBlock(door_x, door_y, door_z, "dark_oak_door", variant="upper", face="WEST") |
| 564 | + drawBlock(exit_x, exit_y, exit_z, "dark_oak_door", variant="upper", face="NORTH") |
| 565 | + drawBlock( |
| 566 | exit_x, exit_y - 1, exit_z, "dark_oak_door", variant="lower", face="NORTH" |
| 567 | ) |
| 425 | 568 | + drawBlock(key_x, key_y - 1, key_z, "stone") |
| 426 | | + drawBlock(key_x, key_y, key_z, "tripwire_hook") |
| 569 | + drawBlock(key_x, key_y, key_z, "gold_block") |
| 570 | + draw_fence(fence_max, start_y + 1, fence_max) |
| 427 | 571 | + """ |
| 428 | 572 | |
| 429 | 573 | </DrawingDecorator> |
| … | … | @@ -442,6 +586,7 @@ missionXML = ( |
| 442 | 586 | <Inventory> |
| 443 | 587 | <InventoryItem slot="0" type="diamond_pickaxe"/> |
| 444 | 588 | <InventoryItem slot="1" type="tripwire_hook"/> |
| 589 | <InventoryBlock slot="2" type="diamond_block" quantity="63"/> |
| 445 | 590 | </Inventory> |
| 446 | 591 | </AgentStart> |
| 447 | 592 | <AgentHandlers> |
| … | … | @@ -452,9 +597,11 @@ missionXML = ( |
| 452 | 597 | <max x="1" y="1" z="1"/> |
| 453 | 598 | </Grid> |
| 454 | 599 | </ObservationFromGrid> |
| 600 | <ObservationFromRay/> |
| 455 | 601 | <ObservationFromRecentCommands/> |
| 456 | | <ContinuousMovementCommands turnSpeedDegs="180"/> |
| 602 | <ContinuousMovementCommands turnSpeedDegs="80"/> |
| 457 | 603 | <AbsoluteMovementCommands /> |
| 604 | <DiscreteMovementCommands /> |
| 458 | 605 | <InventoryCommands/> |
| 459 | 606 | <ChatCommands/> |
| 460 | 607 | <RewardForTouchingBlockType> |
| … | … | @@ -484,23 +631,30 @@ if __name__ == "__main__": |
| 484 | 631 | total_reward = 0 |
| 485 | 632 | agent = malmoWrapper.agent_host |
| 486 | 633 | world_state = agent.getWorldState() |
| 487 | | relocate_agent(agent) |
| 634 | # relocate_agent(agent) |
| 635 | adjust_pitch(agent) |
| 488 | 636 | while world_state.is_mission_running: |
| 637 | # curr_x, curr_y, curr_z = get_curr_loc(agent) |
| 638 | # print(curr_x, curr_y, curr_z) |
| 639 | # nb = input("Enter command: ") |
| 640 | |
| 641 | # nx, ny, nz = nb.split(",") |
| 642 | # turn_to(agent, curr_x, curr_y, curr_z, int(nx), int(ny), int(nz)) |
| 643 | |
| 644 | # agent.sendCommand(nb) |
| 645 | |
| 489 | 646 | world_state = agent.getWorldState() |
| 490 | 647 | if world_state.number_of_rewards_since_last_state > 0: |
| 491 | 648 | total_reward += world_state.rewards[-1].getValue() |
| 492 | 649 | print("total reward minecraft = {}".format(total_reward)) |
| 493 | 650 | ob, rw, _ = go_to_key(agent) |
| 494 | 651 | print("Observation: {}, reward: {}".format(ob, rw)) |
| 495 | | total_reward += rw |
| 496 | 652 | |
| 497 | 653 | ob, rw, _ = go_to_house(agent) |
| 498 | 654 | print("Observation: {}, reward: {}".format(ob, rw)) |
| 499 | | total_reward += rw |
| 500 | 655 | |
| 501 | 656 | ob, rw, _ = go_to_diamonds(agent) |
| 502 | 657 | print("Observation: {}, reward: {}".format(ob, rw)) |
| 503 | | total_reward += rw |
| 504 | 658 | |
| 505 | 659 | time.sleep(2) |
| 506 | 660 | print("total reward = {}".format(total_reward)) |