g.ar_track is now the actual AR. Added g.ar_side that tracks which side is phasing.
The player input to the game is now piped entirely through the UI and g.input_state.
Most input has been split apart, so a "place 6 influence" will allow the player to make 6 moves.
As a result, UI now uses callback functions, which are called when the player provides an input. All callback functions are named _callback.
Another result: all functions that require input halfway can no longer be structured as such. The idiom now should be to use g.stage_list and append the 'continuation'. For example: US uses COMECON for ops and place influence. Assume resolve_card_action is at the end of stage_list (which it should be if the US is playing their AR). Once the US commits the decision, g.stage_complete() will pop resolve_card_action and run it. resolve_card_action should append g.dispose_card and g.trigger_event on stage_list and call g.card_operation_influence, representing that after card_operation_influence, trigger_event will happen, then dispose_card. card_operation_influence will initialize g.input_state to take input for influence operations and return. Once the US then commits the influence operations, stage_complete will pop and run trigger_event. trigger_event should run the COMECON function which will run event_influence for ussr. Once the USSR commits the decision, stage_complete will run dispose_card, which will call stage_complete once it is done. That will call ar_complete, which will call stage_complete when it is done. That will move to the next ar.
As you can see, all functions should call stage_complete at the end if they are a stage and if they are not waiting for input. If they are waiting for input, they should set input_state and append whatever is supposed to run after to stage_list. [Beware of duplicate append! When in doubt, the principle here is that things should be appended to stage_list in functions where it is directly related to its functionality. For example, in the earlier example, dispose_card could be appended to stage_list by trigger_event or COMECON or resolve_card_action. I would do it in resolve_card_action since resolve_card_action has all the necessary information to determine that dispose_card will happen then, and what to do with the card.]
As you might also notice, it is possible for resolve_card_action to instead append dispose_card, event_influence and card_operation_influence to stage_list, then call stage_complete. This achieves the same effect and might be desirable for later, but it doesn't matter right now.
This also means we probably want separate "game effects" that go into the g.basket, rather than the cards themselves. We can probably just put the card name into the basket. The card event function may have to put a continuation into stage_list to get something into the basket only after the card event has happened.
Heavy use of partials. Partials are functions with some arguments already fixed, and can be called with the remaining arguments to run.
numpy dependencies in game_mechanics removed, and mostly replaced with a combination of map, reduce and filter. These are lazy evaluation functions that only run when you actually need the data, and most of the time we only need the data to iterate, which saves some time. In any case, it's nice to not require numpy (although numpy is not that uncommon).
lambda functions are single line functions. lambda x: x * 2 takes a single argument and multiplies it by 2.
Further notes:
The plan is to have dice rolls run in the UI rather than in the Game. This way the game is deterministic. An AI can simulate the results of the different rolls.
Output to the player can eventually be piped via output_queue, but this is more of a two-player-same-screen thing. Essentially you want a player to be able to know what happened without having to scroll up and see confidential information about the other player's hand, so you empty the respective player's output queue (which describes things that happened) only when they are asked for input. I suspect this will also be useful for the AI player in providing concise feedback about the action of their opponent.
Changes:
Further notes:
The plan is to have dice rolls run in the UI rather than in the Game. This way the game is deterministic. An AI can simulate the results of the different rolls.
Output to the player can eventually be piped via output_queue, but this is more of a two-player-same-screen thing. Essentially you want a player to be able to know what happened without having to scroll up and see confidential information about the other player's hand, so you empty the respective player's output queue (which describes things that happened) only when they are asked for input. I suspect this will also be useful for the AI player in providing concise feedback about the action of their opponent.