Emit players in turn order, not registration order

The C code picks a starting player via dice roll but doesn't reorder
the player array. The parser now tracks _first_player_idx and rotates
the players list in get_state() so the UI shows them in actual turn
order.
This commit is contained in:
Jarvis 2026-02-21 11:02:22 +00:00
parent 7a4346a53f
commit 19fc56d982
4 changed files with 147 additions and 76 deletions

View file

@ -426,10 +426,11 @@ class MonopParser:
if not g.get_player(name=name): if not g.get_player(name=name):
p = Player(name, num) p = Player(name, num)
g.players.append(p) g.players.append(p)
# Set current player # Set current player and record turn order start
for i, p in enumerate(g.players): for i, p in enumerate(g.players):
if p.name == name: if p.name == name:
g.current_player_idx = i g.current_player_idx = i
g._first_player_idx = i
break break
g.phase = "playing" g.phase = "playing"
g.game_active = True g.game_active = True
@ -1223,8 +1224,17 @@ class MonopParser:
if "rent" in sq: if "rent" in sq:
sq_out["rent"] = sq["rent"] sq_out["rent"] = sq["rent"]
squares.append(sq_out) squares.append(sq_out)
# Emit players in turn order (rotated so first player is first)
# The C code doesn't reorder the array, it just sets the starting
# index. Turn order is: first_player, first_player+1, ..., wrapping.
if g.players and hasattr(g, '_first_player_idx'):
fp = g._first_player_idx
ordered = g.players[fp:] + g.players[:fp]
else:
ordered = g.players
return { return {
"players": [p.to_dict() for p in g.players], "players": [p.to_dict() for p in ordered],
"currentPlayer": g.current_player.number if g.current_player else None, "currentPlayer": g.current_player.number if g.current_player else None,
"squares": squares, "squares": squares,
"log": g.log[-30:], "log": g.log[-30:],

View file

@ -426,10 +426,11 @@ class MonopParser:
if not g.get_player(name=name): if not g.get_player(name=name):
p = Player(name, num) p = Player(name, num)
g.players.append(p) g.players.append(p)
# Set current player # Set current player and record turn order start
for i, p in enumerate(g.players): for i, p in enumerate(g.players):
if p.name == name: if p.name == name:
g.current_player_idx = i g.current_player_idx = i
g._first_player_idx = i
break break
g.phase = "playing" g.phase = "playing"
g.game_active = True g.game_active = True
@ -1223,8 +1224,17 @@ class MonopParser:
if "rent" in sq: if "rent" in sq:
sq_out["rent"] = sq["rent"] sq_out["rent"] = sq["rent"]
squares.append(sq_out) squares.append(sq_out)
# Emit players in turn order (rotated so first player is first)
# The C code doesn't reorder the array, it just sets the starting
# index. Turn order is: first_player, first_player+1, ..., wrapping.
if g.players and hasattr(g, '_first_player_idx'):
fp = g._first_player_idx
ordered = g.players[fp:] + g.players[:fp]
else:
ordered = g.players
return { return {
"players": [p.to_dict() for p in g.players], "players": [p.to_dict() for p in ordered],
"currentPlayer": g.current_player.number if g.current_player else None, "currentPlayer": g.current_player.number if g.current_player else None,
"squares": squares, "squares": squares,
"log": g.log[-30:], "log": g.log[-30:],

View file

@ -3,7 +3,7 @@
{ {
"name": "alice", "name": "alice",
"number": 1, "number": 1,
"money": 1280, "money": 624,
"location": 21, "location": 21,
"inJail": false, "inJail": false,
"jailTurns": 0, "jailTurns": 0,
@ -13,8 +13,8 @@
{ {
"name": "bob", "name": "bob",
"number": 2, "number": 2,
"money": 1305, "money": 1229,
"location": 16, "location": 23,
"inJail": false, "inJail": false,
"jailTurns": 0, "jailTurns": 0,
"doublesCount": 0, "doublesCount": 0,
@ -23,12 +23,12 @@
{ {
"name": "charlie", "name": "charlie",
"number": 3, "number": 3,
"money": 1260, "money": -12,
"location": 13, "location": 24,
"inJail": false, "inJail": false,
"jailTurns": 0, "jailTurns": 0,
"doublesCount": 0, "doublesCount": 0,
"getOutOfJailFreeCards": 0 "getOutOfJailFreeCards": 1
} }
], ],
"currentPlayer": 3, "currentPlayer": 3,
@ -42,7 +42,7 @@
"id": 1, "id": 1,
"name": "Mediterranean ave. (P)", "name": "Mediterranean ave. (P)",
"type": "property", "type": "property",
"owner": null, "owner": 2,
"mortgaged": false, "mortgaged": false,
"group": "purple", "group": "purple",
"cost": 60, "cost": 60,
@ -57,7 +57,7 @@
"id": 3, "id": 3,
"name": "Baltic ave. (P)", "name": "Baltic ave. (P)",
"type": "property", "type": "property",
"owner": null, "owner": 3,
"mortgaged": false, "mortgaged": false,
"group": "purple", "group": "purple",
"cost": 60, "cost": 60,
@ -72,7 +72,7 @@
"id": 5, "id": 5,
"name": "Reading RR", "name": "Reading RR",
"type": "railroad", "type": "railroad",
"owner": null, "owner": 2,
"mortgaged": false, "mortgaged": false,
"group": "railroad", "group": "railroad",
"cost": 200 "cost": 200
@ -106,7 +106,7 @@
"id": 9, "id": 9,
"name": "Connecticut ave. (L)", "name": "Connecticut ave. (L)",
"type": "property", "type": "property",
"owner": null, "owner": 3,
"mortgaged": false, "mortgaged": false,
"group": "lightblue", "group": "lightblue",
"cost": 120, "cost": 120,
@ -121,7 +121,7 @@
"id": 11, "id": 11,
"name": "St. Charles pl. (V)", "name": "St. Charles pl. (V)",
"type": "property", "type": "property",
"owner": null, "owner": 3,
"mortgaged": false, "mortgaged": false,
"group": "violet", "group": "violet",
"cost": 140, "cost": 140,
@ -131,7 +131,7 @@
"id": 12, "id": 12,
"name": "Electric Co.", "name": "Electric Co.",
"type": "utility", "type": "utility",
"owner": null, "owner": 2,
"mortgaged": false, "mortgaged": false,
"group": "utility", "group": "utility",
"cost": 150 "cost": 150
@ -150,7 +150,7 @@
"id": 14, "id": 14,
"name": "Virginia ave. (V)", "name": "Virginia ave. (V)",
"type": "property", "type": "property",
"owner": null, "owner": 2,
"mortgaged": false, "mortgaged": false,
"group": "violet", "group": "violet",
"cost": 160, "cost": 160,
@ -160,7 +160,7 @@
"id": 15, "id": 15,
"name": "Pennsylvania RR", "name": "Pennsylvania RR",
"type": "railroad", "type": "railroad",
"owner": null, "owner": 1,
"mortgaged": false, "mortgaged": false,
"group": "railroad", "group": "railroad",
"cost": 200 "cost": 200
@ -184,7 +184,7 @@
"id": 18, "id": 18,
"name": "Tennessee ave. (O)", "name": "Tennessee ave. (O)",
"type": "property", "type": "property",
"owner": null, "owner": 1,
"mortgaged": false, "mortgaged": false,
"group": "orange", "group": "orange",
"cost": 180, "cost": 180,
@ -194,7 +194,7 @@
"id": 19, "id": 19,
"name": "New York ave. (O)", "name": "New York ave. (O)",
"type": "property", "type": "property",
"owner": null, "owner": 3,
"mortgaged": false, "mortgaged": false,
"group": "orange", "group": "orange",
"cost": 200, "cost": 200,
@ -224,7 +224,7 @@
"id": 23, "id": 23,
"name": "Indiana ave. (R)", "name": "Indiana ave. (R)",
"type": "property", "type": "property",
"owner": null, "owner": 1,
"mortgaged": false, "mortgaged": false,
"group": "red", "group": "red",
"cost": 220, "cost": 220,
@ -234,7 +234,7 @@
"id": 24, "id": 24,
"name": "Illinois ave. (R)", "name": "Illinois ave. (R)",
"type": "property", "type": "property",
"owner": null, "owner": 1,
"mortgaged": false, "mortgaged": false,
"group": "red", "group": "red",
"cost": 240, "cost": 240,
@ -244,7 +244,7 @@
"id": 25, "id": 25,
"name": "B&O RR", "name": "B&O RR",
"type": "railroad", "type": "railroad",
"owner": null, "owner": 2,
"mortgaged": false, "mortgaged": false,
"group": "railroad", "group": "railroad",
"cost": 200 "cost": 200
@ -263,7 +263,7 @@
"id": 27, "id": 27,
"name": "Ventnor ave. (Y)", "name": "Ventnor ave. (Y)",
"type": "property", "type": "property",
"owner": null, "owner": 1,
"mortgaged": false, "mortgaged": false,
"group": "yellow", "group": "yellow",
"cost": 260, "cost": 260,
@ -273,7 +273,7 @@
"id": 28, "id": 28,
"name": "Water Works", "name": "Water Works",
"type": "utility", "type": "utility",
"owner": null, "owner": 2,
"mortgaged": false, "mortgaged": false,
"group": "utility", "group": "utility",
"cost": 150 "cost": 150
@ -282,7 +282,7 @@
"id": 29, "id": 29,
"name": "Marvin Gardens (Y)", "name": "Marvin Gardens (Y)",
"type": "property", "type": "property",
"owner": null, "owner": 3,
"mortgaged": false, "mortgaged": false,
"group": "yellow", "group": "yellow",
"cost": 280, "cost": 280,
@ -297,7 +297,7 @@
"id": 31, "id": 31,
"name": "Pacific ave. (G)", "name": "Pacific ave. (G)",
"type": "property", "type": "property",
"owner": null, "owner": 3,
"mortgaged": false, "mortgaged": false,
"group": "green", "group": "green",
"cost": 300, "cost": 300,
@ -307,7 +307,7 @@
"id": 32, "id": 32,
"name": "N. Carolina ave. (G)", "name": "N. Carolina ave. (G)",
"type": "property", "type": "property",
"owner": null, "owner": 2,
"mortgaged": false, "mortgaged": false,
"group": "green", "group": "green",
"cost": 300, "cost": 300,
@ -322,7 +322,7 @@
"id": 34, "id": 34,
"name": "Pennsylvania ave. (G)", "name": "Pennsylvania ave. (G)",
"type": "property", "type": "property",
"owner": null, "owner": 3,
"mortgaged": false, "mortgaged": false,
"group": "green", "group": "green",
"cost": 320, "cost": 320,
@ -332,7 +332,7 @@
"id": 35, "id": 35,
"name": "Short Line RR", "name": "Short Line RR",
"type": "railroad", "type": "railroad",
"owner": null, "owner": 1,
"mortgaged": false, "mortgaged": false,
"group": "railroad", "group": "railroad",
"cost": 200 "cost": 200
@ -346,7 +346,7 @@
"id": 37, "id": 37,
"name": "Park place (D)", "name": "Park place (D)",
"type": "property", "type": "property",
"owner": null, "owner": 1,
"mortgaged": false, "mortgaged": false,
"group": "darkblue", "group": "darkblue",
"cost": 350, "cost": 350,
@ -361,7 +361,7 @@
"id": 39, "id": 39,
"name": "Boardwalk (D)", "name": "Boardwalk (D)",
"type": "property", "type": "property",
"owner": null, "owner": 3,
"mortgaged": false, "mortgaged": false,
"group": "darkblue", "group": "darkblue",
"cost": 400, "cost": 400,
@ -370,99 +370,150 @@
], ],
"log": [ "log": [
{ {
"text": "roll is 4, 6", "text": "roll is 6, 5",
"player": "charlie",
"timestamp": "2026-02-21 11:01:40"
},
{
"text": "Passed GO \u2014 collected $200",
"player": "charlie",
"timestamp": "2026-02-21 11:01:40"
},
{
"text": "Landed on Income Tax",
"player": "charlie",
"timestamp": "2026-02-21 11:01:41"
},
{
"text": "alice's turn \u2014 $289 on Just Visiting",
"player": "alice", "player": "alice",
"timestamp": "2026-02-21 10:55:12" "timestamp": "2026-02-21 11:01:47"
}, },
{ {
"text": "Landed on Just Visiting", "text": "Trade completed between alice and bob",
"player": null
},
{
"text": "alice's turn \u2014 $484 on Just Visiting",
"player": "alice", "player": "alice",
"timestamp": "2026-02-21 10:55:13" "timestamp": "2026-02-21 11:01:58"
}, },
{ {
"text": "bob's turn \u2014 $1500 on === GO ===", "text": "roll is 3, 2",
"player": "alice",
"timestamp": "2026-02-21 11:01:59"
},
{
"text": "Landed on Pennsylvania RR",
"player": "alice",
"timestamp": "2026-02-21 11:01:59"
},
{
"text": "bob's turn \u2014 $1279 on Electric Co.",
"player": "bob", "player": "bob",
"timestamp": "2026-02-21 10:55:14" "timestamp": "2026-02-21 11:02:00"
}, },
{ {
"text": "roll is 5, 2", "text": "roll is 1, 5",
"player": "bob", "player": "bob",
"timestamp": "2026-02-21 10:55:15" "timestamp": "2026-02-21 11:02:02"
}, },
{ {
"text": "Landed on Chance i", "text": "Landed on Tennessee ave. (O)",
"player": "bob", "player": "bob",
"timestamp": "2026-02-21 10:55:15" "timestamp": "2026-02-21 11:02:02"
}, },
{ {
"text": "Pay Poor Tax of $15", "text": "Paid $14 rent to alice",
"player": "bob" "player": "bob"
}, },
{ {
"text": "charlie's turn \u2014 $1500 on === GO ===", "text": "charlie's turn \u2014 $78 on Income Tax",
"player": "charlie", "player": "charlie",
"timestamp": "2026-02-21 10:55:17" "timestamp": "2026-02-21 11:02:04"
}, },
{ {
"text": "roll is 3, 3", "text": "roll is 6, 5",
"player": "charlie", "player": "charlie",
"timestamp": "2026-02-21 10:55:19" "timestamp": "2026-02-21 11:02:05"
}, },
{ {
"text": "Landed on Oriental ave. (L)", "text": "Landed on Pennsylvania RR",
"player": "charlie", "player": "charlie",
"timestamp": "2026-02-21 10:55:19" "timestamp": "2026-02-21 11:02:05"
}, },
{ {
"text": "charlie's turn \u2014 $1400 on Oriental ave. (L)", "text": "Paid $50 rent to alice",
"player": "charlie", "player": "charlie"
"timestamp": "2026-02-21 10:55:22"
}, },
{ {
"text": "roll is 1, 6", "text": "alice's turn \u2014 $548 on Pennsylvania RR",
"player": "charlie",
"timestamp": "2026-02-21 10:55:23"
},
{
"text": "Landed on States ave. (V)",
"player": "charlie",
"timestamp": "2026-02-21 10:55:23"
},
{
"text": "alice's turn \u2014 $1500 on Just Visiting",
"player": "alice", "player": "alice",
"timestamp": "2026-02-21 10:55:25" "timestamp": "2026-02-21 11:02:07"
}, },
{ {
"text": "roll is 5, 6", "text": "roll is 5, 1",
"player": "alice", "player": "alice",
"timestamp": "2026-02-21 10:55:26" "timestamp": "2026-02-21 11:02:08"
}, },
{ {
"text": "Landed on Kentucky ave. (R)", "text": "Landed on Kentucky ave. (R)",
"player": "alice", "player": "alice",
"timestamp": "2026-02-21 10:55:27" "timestamp": "2026-02-21 11:02:09"
}, },
{ {
"text": "bob's turn \u2014 $1485 on Chance i", "text": "bob's turn \u2014 $1265 on Tennessee ave. (O)",
"player": "bob", "player": "bob",
"timestamp": "2026-02-21 10:55:29" "timestamp": "2026-02-21 11:02:10"
}, },
{ {
"text": "roll is 3, 6", "text": "roll is 1, 1",
"player": "bob", "player": "bob",
"timestamp": "2026-02-21 10:55:30" "timestamp": "2026-02-21 11:02:11"
}, },
{ {
"text": "Landed on St. James pl. (O)", "text": "Landed on Free Parking",
"player": "bob", "player": "bob",
"timestamp": "2026-02-21 10:55:30" "timestamp": "2026-02-21 11:02:11"
}, },
{ {
"text": "charlie's turn \u2014 $1260 on States ave. (V)", "text": "bob's turn \u2014 $1265 on Free Parking",
"player": "bob",
"timestamp": "2026-02-21 11:02:13"
},
{
"text": "roll is 1, 2",
"player": "bob",
"timestamp": "2026-02-21 11:02:14"
},
{
"text": "Landed on Indiana ave. (R)",
"player": "bob",
"timestamp": "2026-02-21 11:02:14"
},
{
"text": "Paid $36 rent to alice",
"player": "bob"
},
{
"text": "charlie's turn \u2014 $28 on Pennsylvania RR",
"player": "charlie", "player": "charlie",
"timestamp": "2026-02-21 10:55:32" "timestamp": "2026-02-21 11:02:16"
},
{
"text": "roll is 5, 4",
"player": "charlie",
"timestamp": "2026-02-21 11:02:17"
},
{
"text": "Landed on Illinois ave. (R)",
"player": "charlie",
"timestamp": "2026-02-21 11:02:18"
},
{
"text": "Paid $40 rent to alice",
"player": "charlie"
} }
], ],
"lastUpdated": "2026-02-21T10:55:32.750315+00:00" "lastUpdated": "2026-02-21T11:02:22.605328+00:00"
} }