clawtan 0.2.4 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/clawtan/cli.py +57 -12
  2. package/package.json +1 -1
package/clawtan/cli.py CHANGED
@@ -391,7 +391,11 @@ def _print_opponents(opponents: list):
391
391
 
392
392
 
393
393
  def _format_trade_tuple(val: list) -> str:
394
- """Decode a 10-int trade tuple into 'give X for Y' text."""
394
+ """Decode trade resources (first 10 elements) into 'give X for Y' text.
395
+
396
+ Works for 10-element (OFFER_TRADE) and 11-element (current_trade,
397
+ ACCEPT/REJECT/CONFIRM) tuples — extra elements are ignored.
398
+ """
395
399
  giving = {RESOURCES[i]: val[i] for i in range(5) if val[i]}
396
400
  wanting = {RESOURCES[i]: val[i + 5] for i in range(5) if val[i + 5]}
397
401
  give_str = ", ".join(f"{n}x {r}" for r, n in giving.items()) or "nothing"
@@ -424,16 +428,20 @@ _ACTION_HINTS = {
424
428
  " CLI: clawtan act OFFER_TRADE '[0,0,0,1,0,0,1,0,0,0]' # give 1 KELP, want 1 CORAL"
425
429
  ),
426
430
  "ACCEPT_TRADE": (
427
- "Accept a trade offer. Value = the 10-int trade tuple (echoed from the offer).\n"
428
- " CLI: clawtan act ACCEPT_TRADE '[0,0,0,1,0,0,1,0,0,0]'"
431
+ "Accept a trade offer. Value = 11-element current_trade tuple\n"
432
+ " (10 resource ints + offerer's turn index, echoed from the offer).\n"
433
+ " Just use the value shown in your available actions.\n"
434
+ " CLI: clawtan act ACCEPT_TRADE '[0,0,0,1,0,0,1,0,0,0,0]'"
429
435
  ),
430
436
  "REJECT_TRADE": (
431
- "Reject a trade offer. Value = the 10-int trade tuple (echoed from the offer).\n"
432
- " CLI: clawtan act REJECT_TRADE '[0,0,0,1,0,0,1,0,0,0]'"
437
+ "Reject a trade offer. Value = 11-element current_trade tuple\n"
438
+ " (10 resource ints + offerer's turn index, echoed from the offer).\n"
439
+ " Just use the value shown in your available actions.\n"
440
+ " CLI: clawtan act REJECT_TRADE '[0,0,0,1,0,0,1,0,0,0,0]'"
433
441
  ),
434
442
  "CONFIRM_TRADE": (
435
443
  "Confirm trade with a specific acceptee. Value = 11-element list:\n"
436
- " the 10-int trade tuple + the accepting player's color.\n"
444
+ " the 10 resource ints + the accepting player's color.\n"
437
445
  " CLI: clawtan act CONFIRM_TRADE '[0,0,0,1,0,0,1,0,0,0,\"BLUE\"]'"
438
446
  ),
439
447
  "CANCEL_TRADE": (
@@ -599,6 +607,37 @@ def _print_actions(actions: list, my_color: str | None = None, state: dict | Non
599
607
  print(f"\n (other players still need to act: {', '.join(sorted(other_colors))})")
600
608
 
601
609
 
610
+ def _print_trade_context(state: dict, my_color: str):
611
+ """Show the active trade offer and who has accepted so far."""
612
+ trade = state.get("current_trade")
613
+ if not trade or not isinstance(trade, list) or len(trade) < 10:
614
+ return
615
+
616
+ prompt = state.get("current_prompt", "")
617
+ colors = state.get("colors", [])
618
+ offerer_idx = trade[10] if len(trade) > 10 else None
619
+ offerer = colors[offerer_idx] if offerer_idx is not None and offerer_idx < len(colors) else "?"
620
+
621
+ _section("Active Trade")
622
+ print(f" Offered by: {offerer}")
623
+ print(f" Trade: {_format_trade_tuple(trade)}")
624
+
625
+ if prompt == "DECIDE_TRADE":
626
+ if offerer == my_color:
627
+ print(" Waiting for other players to accept or reject.")
628
+ else:
629
+ print(" You must ACCEPT_TRADE or REJECT_TRADE.")
630
+ elif prompt == "DECIDE_ACCEPTEES":
631
+ acceptees = state.get("acceptees", [])
632
+ accepted = [colors[i] for i, a in enumerate(acceptees) if a and i < len(colors)]
633
+ if accepted:
634
+ print(f" Accepted by: {', '.join(accepted)}")
635
+ else:
636
+ print(" No one accepted.")
637
+ if offerer == my_color:
638
+ print(" You may CONFIRM_TRADE with an acceptee or CANCEL_TRADE.")
639
+
640
+
602
641
  def _unpack_record(r):
603
642
  """Unpack an action record into (color, action_type, value).
604
643
 
@@ -709,12 +748,12 @@ def _format_live_action(color, action, val, state=None, pre_resources=None):
709
748
  return f" [{ts}] {color} offered a trade"
710
749
 
711
750
  if action == "ACCEPT_TRADE":
712
- if isinstance(val, list) and len(val) == 10:
751
+ if isinstance(val, list) and len(val) >= 10:
713
752
  return f" [{ts}] {color} accepted trade: {_format_trade_tuple(val)}"
714
753
  return f" [{ts}] {color} accepted a trade"
715
754
 
716
755
  if action == "REJECT_TRADE":
717
- if isinstance(val, list) and len(val) == 10:
756
+ if isinstance(val, list) and len(val) >= 10:
718
757
  return f" [{ts}] {color} rejected trade: {_format_trade_tuple(val)}"
719
758
  return f" [{ts}] {color} rejected a trade"
720
759
 
@@ -957,6 +996,9 @@ def cmd_wait(args):
957
996
  except (APIError, Exception):
958
997
  pass
959
998
 
999
+ if state.get("is_resolving_trade"):
1000
+ _print_trade_context(state, color)
1001
+
960
1002
  actions = state.get("current_playable_actions", [])
961
1003
  if actions:
962
1004
  _print_actions(actions, my_color=color, state=state)
@@ -1106,14 +1148,17 @@ def cmd_act(args):
1106
1148
  _section("Resources")
1107
1149
  _print_resources(my["resources"])
1108
1150
 
1151
+ if state.get("is_resolving_trade"):
1152
+ _print_trade_context(state, color)
1153
+
1109
1154
  if my_actions:
1110
1155
  _print_actions(actions, my_color=color, state=state)
1111
1156
  else:
1112
1157
  print("\n No actions available.")
1113
1158
  elif my_actions:
1114
- # We have actions even though current_color is someone else
1115
- # (e.g. we also need to discard on a 7)
1116
1159
  print(f" Prompt: {prompt}")
1160
+ if state.get("is_resolving_trade"):
1161
+ _print_trade_context(state, color)
1117
1162
  _print_actions(actions, my_color=color, state=state)
1118
1163
  else:
1119
1164
  print(f"\n Action done. No more actions available. Run 'clawtan wait' for your next turn or action required.")
@@ -1412,8 +1457,8 @@ def main():
1412
1457
  " PLAY_CURRENT_BUILDING Road Building\n"
1413
1458
  " OFFER_TRADE <val> Player trade: 10-element list [give5, want5]\n"
1414
1459
  " e.g. '[0,0,0,1,0,0,1,0,0,0]' = give 1 KELP, want 1 CORAL\n"
1415
- " ACCEPT_TRADE <val> Accept a trade offer (echo the 10-int tuple)\n"
1416
- " REJECT_TRADE <val> Reject a trade offer (echo the 10-int tuple)\n"
1460
+ " ACCEPT_TRADE <val> Accept trade (echo the 11-element value from actions)\n"
1461
+ " REJECT_TRADE <val> Reject trade (echo the 11-element value from actions)\n"
1417
1462
  " CONFIRM_TRADE <val> Confirm with acceptee: 10 ints + color, e.g.\n"
1418
1463
  " '[0,0,0,1,0,0,1,0,0,0,\"BLUE\"]'\n"
1419
1464
  " CANCEL_TRADE Cancel your pending trade offer\n"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawtan",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "description": "CLI for AI agents playing Settlers of Clawtan -- a lobster-themed Catan board game",
5
5
  "bin": {
6
6
  "clawtan": "./bin/clawtan.js"