CITS3001-Algorithms-Agents-.../play_manual.py
2022-10-24 21:04:39 +08:00

199 lines
6.1 KiB
Python

from copy import deepcopy
from datetime import datetime
import math
import pathlib
import pickle
from typing import List
from etc.custom_float import Uncertainty
from etc.gamestate import GameState, Winner
from etc.messages import Message, Opinion
from agents.blue import BlueAgent
from agents.red import RedAgent
import play_config as cfg
def rand_rounds(gs: GameState) -> GameState:
blue_gamestate = deepcopy(gs)
gs.blue_agent.smart_influence(gs)
red_gamestate = deepcopy(gs)
gs.red_agent.smart_influence(gs)
# gs.draw_green_network()
# gs.green_round()
# gs.draw_green_network()
# spy = bool(gs.rand.getrandbits(1))
# spy = False
gs.green_round()
gs.draw_green_network()
gs.red_agent.update_short_term_mem(red_gamestate, gs)
gs.blue_agent.update_short_term_mem(blue_gamestate, gs)
gs.iteration += 1
return gs
def main():
sel_parameters = input_opts("""Would you like to select parameters?
[y] -> Yes
[n] -> No
> """, ['y', 'n'])
if sel_parameters == 'y':
select_parameters()
cfg.ENABLE_SNAPSHOTS = ('y' == input_opts("""Would you like to enable snapshots?
[y] -> Yes
[n] -> No
> """, ['y', 'n']))
if cfg.ENABLE_SNAPSHOTS:
snapshot_path = pathlib.Path(cfg.GAMESTATE_PARAMETER_SNAPSHOT_OUTPUT_DIR)
snapshot_path.mkdir(parents=True, exist_ok=True)
cfg.ENABLE_GRAPHICS = ('y' == input_opts("""Enable graphics?
Note that this option is currently exporting to an image file for compatibility on headless operating systems (WSL)
[y] -> Graphics
[n] -> No graphics
> """, ['y', 'n']))
while True:
print("Starting new game")
state_buffer: List[GameState] = []
# gs: GameState = GameState.short_init((100, 0.05, 0.5), (10, 0.5))
gs: GameState = GameState(
green_agents=(cfg.N_GREEN_AGENT, cfg.P_GREEN_AGENT_CONNECTION, cfg.P_GREEN_AGENT_BLUE),
gray_agents=(cfg.N_GRAY_AGENT, cfg.P_GRAY_AGENT_FRIENDLY),
uncertainty_interval=cfg.INITIAL_UNCERTAINTY_RANGE,
seed=None, graphics=cfg.ENABLE_GRAPHICS)
player = input_opts("""Choose a team
[r] -> Red
[b] -> Blue
[n] -> None
> """, ['r', 'b', 'n'])
player: Opinion = {
'r': Opinion.RED,
'b': Opinion.BLUE,
'n': Opinion.UNDEFINED
}[player]
state_buffer.append(deepcopy(gs))
while gs.winner == Winner.NO_WINNER:
print(gs.print_gamestate_pretty())
print("Blue turn")
blue_gamestate = deepcopy(gs)
if player == Opinion.BLUE:
option = select_potency(BlueAgent.choices())
gs.blue_agent.influence(gs, option)
else:
gs.blue_agent.dumb_influence(gs)
print("Red turn")
red_gamestate = deepcopy(gs)
if player == Opinion.RED:
option = select_potency(RedAgent.choices())
gs.red_agent.influence(gs, option)
else:
gs.red_agent.dumb_influence(gs)
print("Green turn")
gs.green_round()
gs.draw_green_network()
gs.red_agent.update_short_term_mem(red_gamestate, gs)
gs.blue_agent.update_short_term_mem(blue_gamestate, gs)
gs.iteration += 1
gs.update_winner()
state_buffer.append(deepcopy(gs))
gs.close()
print(f"""
Game over
Round {gs.iteration}, reason {gs.winner}
Winner {Winner.winner_opinion(gs.winner)}""")
if player != Opinion.UNDEFINED:
print("YOU WIN 🎉" if Winner.winner_opinion(gs.winner) == player else "YOU LOSE 💀")
print(gs.print_gamestate_pretty())
input("Press enter to continue...")
# Save snapshot of game
if cfg.ENABLE_SNAPSHOTS:
with snapshot_path.joinpath(f"game_snapshot_{datetime.now().isoformat().replace(':','_')}.bin").open("wb") as f:
pickle.dump(state_buffer, f, protocol=pickle.HIGHEST_PROTOCOL)
def select_potency(messages: List[Message]) -> Message:
prompt_str = "Choose a potency\n"
for i in range(0, len(messages)):
prompt_str += f"[{i}] -> {str(messages[i])}\n"
return messages[input_p_int(prompt_str, 0, len(messages))]
def select_parameters() -> None:
# Override config defaults
print("\nBlue agent\n---")
cfg.INITIAL_BLUE_ENERGY = input_float("Blue agent initial energy?\n> ")
print("\nBounds of uniform uncertainty distribution at start of game for green agents\n---")
cfg.INITIAL_UNCERTAINTY_RANGE = (input_uncertainty("Lower\n> "), input_uncertainty("Upper\n> "))
print("\nGreen agents\n---")
cfg.N_GREEN_AGENT = input_p_int("Number of green agents\n> ")
cfg.P_GREEN_AGENT_CONNECTION = input_probability("Probability of green agent connections [0,1]\n> ")
cfg.P_GREEN_AGENT_BLUE = input_p_int("Probability of green agents initialized to blue opinion\n> ")
print("\nGray agents\n---")
cfg.N_GRAY_AGENT = input_p_int("Number of gray agents\n> ")
cfg.P_GRAY_AGENT_FRIENDLY = input_probability("Probability of gray agents being blue\n> ")
def input_probability(prompt: str) -> float:
while True:
value = input_T(prompt, float)
if value > 0.0 and value < 1.0:
return value
else:
print("Invalid input")
def input_p_int(prompt: str, l_=0, u_=math.inf) -> int:
while True:
value = input_T(prompt, int)
if value >= l_ and value < u_:
return value
else:
print("Invalid input")
def input_float(prompt: str) -> float:
return input_T(prompt, float)
def input_uncertainty(prompt: str) -> Uncertainty:
return input_T(prompt, Uncertainty)
def input_T(prompt: str, type):
num: type = None
while num is None:
try:
num = type(input(prompt))
except ValueError:
print("Invalid input")
return num
def input_opts(prompt: str, opts: List[str]) -> str:
option: str = ""
while option not in opts:
if len(option) > 0:
print("Invalid input")
option = input(prompt).strip().lower()
return option
if __name__ == "__main__":
main()