Skip to content

Instantly share code, notes, and snippets.

@varun93
Created March 22, 2019 18:08
Show Gist options
  • Save varun93/19afef2ac4ec87ec483e3cb08bf881e5 to your computer and use it in GitHub Desktop.
Save varun93/19afef2ac4ec87ec483e3cb08bf881e5 to your computer and use it in GitHub Desktop.
from config import log
from dice import Dice
import constants
from cards import Cards
import copy
# import timeout_decorator
from state import State,Phase,Reason
# autobahn imports
from os import environ
from twisted.internet import reactor
from twisted.internet.defer import inlineCallbacks
from autobahn.twisted.wamp import ApplicationSession, ApplicationRunner
# Game state
# track which which agent(s) I am talking to
# What is the action I am performing
#
class Component(ApplicationSession):
"""
An application component calling the different backend procedures.
"""
@inlineCallbacks
def startGame(self,agents, end_game_uri):
result = yield self.runGame(agents)
print(result)
# the reason for not notifying the agent
# directly is to make sure that message is sent via game gen
for agent in agents:
print(end_game_uri)
yield self.publish(end_game_uri,agent,result)
@wamp.subscribe("auction_result"):
def method(self,agent_id):
#
#
# checking
@wamp.subscribe("auction_result"):
def method(self,agent_id):
#
# checking
@wamp.subscribe("auction_result"):
def method(self,agent_id):
#
#
# checking
def action1_publish(self,agent_id):
#
#
# self.publish()
def action2_publish(self,agent_id):
#
#
# self.publish()
@inlineCallbacks
def onJoin(self, details):
print("session attached")
self.CHANCE_GET_OUT_OF_JAIL_FREE = 40
self.COMMUNITY_GET_OUT_OF_JAIL_FREE = 41
self.BOARD_SIZE = 40
self.PASSING_GO_MONEY = 200
self.JUST_VISTING = 10
self.OWNED_BY_BANK = -1
self.JAIL = -1
self.dice = None
"""CONFIGURATION SETTINGS"""
self.TOTAL_NO_OF_TURNS = 100
self.INITIAL_CASH = 1500
self.game_id = 1
self.game_start_uri = 'com.game{}.start_game'.format(self.game_id)
yield self.subscribe(self.startGame, self.game_start_uri)
# this will be pulled in from the command line
# result = yield self.runGame(["1","2"])
# print(result)
# self.leave()
def onDisconnect(self):
print("disconnected")
if reactor.running:
reactor.stop()
"""
STATE PROPERTIES
"""
# def getPlayer(self,playerId):
# if playerId in self.agents:
# return
# # for agent in self.agents:
# if agent.id==playerId:
# return agent
# return None
def updateState(self, state, dimensionOneIndex, dimensionTwoIndex, valueToUpdate):
if dimensionTwoIndex is None:
state[dimensionOneIndex] = valueToUpdate
else:
state[dimensionOneIndex][dimensionTwoIndex] = valueToUpdate
def transformState(self,state):
transformedState = []
for element in state:
if isinstance(element, list):
transformedState.append(tuple(element))
elif isinstance(element, dict):
transformedState.append(tuple([element[1] for element in element.items()]))
else:
transformedState.append(element)
return tuple(transformedState)
"""
Validation function which checks if the variable `var` can be typecast to datatype `thetype`.
If there was any exception encountered, return the default value specified
"""
def typecast(self,val,thetype,default):
try:
if (thetype == bool) and not isinstance(val, thetype):
return default
return thetype(val)
except:
return default
#Function checks cash passed in through actions by the agent.
#If cash can't be typecast to int, the cash amount is considered invalid and invalid flows for defaulting would take place.
def check_valid_cash(self,cash):
try:
cash = int(cash)
except:
return 0
if cash < 0:
return 0
return cash
#Generator for circular range
def crange(self,start, end, modulo):
if start > end:
while start < modulo:
yield start
start += 1
start = 0
while start <= end:
yield start
start += 1
def conductBSM(self):
"""Returns the type of action. Also checks if the action is valid."""
def checkActionType(action):
if not ( isinstance(action, list) or isinstance(action, tuple) ) or len(action)<2:
return "N"
type = action[0]
if type=="BHS":
if not ( isinstance(action[1], list) or isinstance(action[1], tuple) ):
return "N"
else:
for prop in action[1]:
if not ( isinstance(prop, list) or isinstance(prop, tuple) ) or len(prop)<2:
return "N"
else:
firstElem = self.typecast(prop[0],int,-1)
secondElem = self.typecast(prop[1],int,-1)
if firstElem<0 or firstElem>self.BOARD_SIZE-1:
return "N"
if secondElem<0 or secondElem>4:
return "N"
elif type=="S":
if not ( isinstance(action[1], list) or isinstance(action[1], tuple) ):
return "N"
else:
for prop in action[1]:
if not ( isinstance(prop, list) or isinstance(prop, tuple) ) or len(prop)<3:
return "N"
else:
firstElem = self.typecast(prop[0],int,-1)
secondElem = self.typecast(prop[1],int,-1)
thirdElem = self.typecast(prop[2], bool, False)
if firstElem<0 or firstElem>self.BOARD_SIZE-1:
return "N"
if secondElem<0 or secondElem>4:
return "N"
elif type == "M" or type=="BHT":
if not isinstance(action[1], list) and not isinstance(action[1], tuple):
return "N"
else:
for prop in action[1]:
firstElem = self.typecast(prop,int,-1)
if firstElem<0 or firstElem>self.BOARD_SIZE-1:
return "N"
return type
def hasBuyingCapability(playerId,properties):
playerCash = self.state.getCash(playerId)
for propertyId,constructions in properties:
space = constants.board[propertyId]
playerCash -= space['build_cost']*constructions
if playerCash < 0:
break
return playerCash >= 0
# house can be built only if you own a monopoly of colours
# double house can be built only if I have built one house in each colour
# order of the tuples to be taken into account
def handleBuyHouses(playerId,properties):
playerCash = self.state.getCash(playerId)
for propertyId,constructions in properties:
houseCount = self.state.getNumberOfHouses(propertyId)
houseCount += constructions
playerCash -= (constants.board[propertyId]['build_cost']*constructions)
self.state.setNumberOfHouses(propertyId,houseCount)
self.state.setCash(playerId,playerCash)
return True
def handleSell(playerId,properties):
playerCash = self.state.getCash(playerId)
for propertyId,constructions,hotel in properties:
space = constants.board[propertyId]
if hotel: constructions+=1
houseCount = self.state.getNumberOfHouses(propertyId)
houseCount -= constructions
playerCash += int(space['build_cost']*0.5*constructions)
self.state.setNumberOfHouses(propertyId,houseCount)
self.state.setCash(playerId,playerCash)
return True
# If property is mortgaged, player gets back 50% of the price.
# If the player tries to unmortgage something and he doesn't have the money, the entire operation fails.
# If the player tries to mortgage an invalid property, entire operation fails.
@inlineCallbacks
def handleMortgage(playerId,properties):
playerCash = self.state.getCash(playerId)
mortgageRequests = []
unmortgageRequests = []
for propertyId in properties:
if self.state.getPropertyOwner(propertyId)!=playerId:
return False
#It could be that the player is getting money to unmortgage a property
#by mortgaging other properties. Hence, processing mortgage requests first.
if self.state.isPropertyMortgaged(propertyId):
unmortgageRequests.append(propertyId)
else:
mortgageRequests.append(propertyId)
for propertyId in mortgageRequests:
#There should be no houses on a property to be mortgaged or in any other property in the monopoly.
if self.state.getNumberOfHouses(propertyId)>0:
return False
space = constants.board[propertyId]
for monopolyPropertyId in space["monopoly_group_elements"]:
if self.state.getNumberOfHouses(propertyId)>0:
return False
mortagePrice = int(constants.board[propertyId]['price']/2)
playerCash += mortagePrice
log("bsm","Player "+str(playerId)+" wants to mortgage.")
for propertyId in unmortgageRequests:
unmortgagePrice = int(constants.board[propertyId]['price']/2)
if propertyId in self.mortgagedDuringTrade:
self.mortgagedDuringTrade.remove(propertyId)
else:
unmortgagePrice = int(unmortgagePrice*1.1)
if playerCash >= unmortgagePrice:
playerCash -= unmortgagePrice
else:
return False
log("bsm","Player "+str(playerId)+" wants to unmortgage.")
log("bsm",str(properties))
for propertyId in properties:
self.state.setPropertyMortgaged(propertyId,not self.state.isPropertyMortgaged(propertyId))
self.state.setCash(playerId,playerCash)
"""
BSMT will be carried out as decision rounds where each player is asked for his BSMT action during that round.
If all the player's don't want to take BSMT actions in a given round, then the BSMT phase ends.
If a player decides he doesn't want to take any BSMT actions in a given decision round, he can still make BSMT actions in later decision rounds.
This is done so that he can react to the BSMT decisions made by other players.
TODO:
Find a way to ensure that BSMT doesn't go on forever.
"""
currentPlayerIndex = self.state.getCurrentPlayerIndex()
"""Currently, BSM could go on forever."""
while True:
mortgageRequests = []
buyingHousesRequests = []
buyingHotelsRequests = []
sellingRequests = []
"""Getting the actions for BSM from all the players"""
actionCount=0
for i in self.crange(currentPlayerIndex,currentPlayerIndex-1,self.TOTAL_NO_OF_PLAYERS):
playerId = self.PLAY_ORDER[i]
if not self.state.hasPlayerLost(playerId):
action = yield self.runPlayerOnStateWithTimeout(playerId,"BSM")
actionType = checkActionType(action) #Some basic validation like syntax,type checking and value range.
if actionType=="M":
mortgageRequests.append((playerId,action[1]))
actionCount+=1
elif actionType=="BHS":
if self.state.isBuyingHousesSequenceValid(playerId,action[1]) and hasBuyingCapability(playerId,action[1]):
buyingHousesRequests.append((playerId,action[1]))
log("bsm","Player "+str(playerId)+" wants to buy houses.")
log("bsm",str(action[1]))
actionCount+=1
elif actionType=="BHT":
if self.state.isBuyingHotelSequenceValid(playerId,action[1]):
buyingHotelsRequests.append((playerId,action[1]))
log("bsm","Player "+str(playerId)+" wants to buy hotels.")
log("bsm",str(action[1]))
actionCount+=1
elif actionType=="S":
if self.state.isSellingSequenceValid(playerId,action[1]):
sellingRequests.append((playerId,action[1]))
log("bsm","Player "+str(playerId)+" wants to sell houses/hotels.")
log("bsm",str(action[1]))
actionCount+=1
if actionCount==0:
break #Stop BSM if there are no valid BSM requests during a given turn
"""Selling Requests"""
finishedSellingRequests = []
for playerId,request in sellingRequests:
housesNeeded,hotelsNeeded = self.state.evaluateSellingSequence(request)
if housesNeeded<=0 and hotelsNeeded<=0:
handleSell(playerId, request)
finishedSellingRequests.append(playerId)
sellingRequests = [entry for entry in sellingRequests if entry[0] not in finishedSellingRequests]
housesRemaining = self.state.getHousesRemaining()
housesNeededForBHS = 0
for _,request in buyingHousesRequests:
housesNeededForBHS += self.state.evaluateBuyingHousesSequence(request)
housesRemaining -= housesNeededForBHS
for playerId,request in sellingRequests:
housesNeeded,hotelsNeeded = self.state.evaluateSellingSequence(request)
if housesNeeded<=housesRemaining:
handleSell(playerId, request)
housesRemaining-=housesNeeded
else: break
"""Mortgage/Unmortgage requests"""
for playerId,mortgageRequest in mortgageRequests:
yield handleMortgage(playerId,mortgageRequest)
"""Buying Hotels Requests"""
hotelsRemaining = self.state.getHotelsRemaining()
hotelsForBHT = 0
for _,request in buyingHotelsRequests:
hotelsForBHT += len(request)
if hotelsRemaining-hotelsForBHT>=0:
for playerId,request in buyingHotelsRequests:
self.state.buyHotelSequence(playerId,request)
else:
#TODO: AUCTION FOR HOTELS
#All the hotel requests are in: buyingHotelsRequests
self.auctionInBSM(buyingHotelsRequests,"hotels")
"""Buying Houses Requests"""
housesRemaining = self.state.getHousesRemaining()
if housesRemaining-housesNeededForBHS>=0:
for playerId,request in buyingHousesRequests:
handleBuyHouses(playerId,request)
else:
#TODO: AUCTION FOR HOUSES
#All the hotel requests are in: buyingHousesRequests
self.auctionInBSM(buyingHousesRequests)
""" ACTION METHODS """
@inlineCallbacks
def conductTrade(self):
def validPropertyToTrade(playerId, propertyId):
propertyId = self.typecast(propertyId,int,-1)
if propertyId<0 or propertyId>self.BOARD_SIZE-1:
return False
if not self.state.rightOwner(playerId,propertyId):
return False
if self.state.getNumberOfHouses(propertyId) > 0:
return False
return True
#Syntax: (otherAgentId,cashOffer,propertiesOffer,cashRequest,propertiesRequest)
def validateTradeAction(action):
if not ( isinstance(action, list) or isinstance(action, tuple) ) or len(action)<5:
return False
otherAgentId,cashOffer,propertiesOffer,cashRequest,propertiesRequest = action
currentPlayerId = self.state.getCurrentPlayerId()
passed = False
if otherAgentId == currentPlayerId:
return False
for playerId in self.PLAY_ORDER:
if otherAgentId == playerId:
passed = True
break
if not passed:
return False
cashOffer = self.check_valid_cash(cashOffer)
cashRequest = self.check_valid_cash(cashRequest)
currentPlayerCash = self.state.getCash(currentPlayerId)
otherPlayerCash = self.state.getCash(otherAgentId)
if cashOffer > currentPlayerCash:
return False
if cashRequest > otherPlayerCash:
return False
if not isinstance(propertiesOffer, list) and not isinstance(propertiesOffer, tuple):
return False
else:
for propertyId in propertiesOffer:
if not validPropertyToTrade(currentPlayerId, propertyId):
return False
if not isinstance(propertiesRequest, list) and not isinstance(propertiesRequest, tuple):
return False
else:
for propertyId in propertiesRequest:
if not validPropertyToTrade(otherAgentId, propertyId):
return False
return True
currentPlayerIndex = self.state.getCurrentPlayerIndex()
while True:
actionCount=0
for i in self.crange(currentPlayerIndex,currentPlayerIndex-1,self.TOTAL_NO_OF_PLAYERS):
playerId = self.PLAY_ORDER[i]
if not self.state.hasPlayerLost(playerId):
action = yield self.runPlayerOnStateWithTimeout(playerId,"TRADE")
validTrade = yield validateTradeAction(action)
if validTrade:
otherAgentId,cashOffer,propertiesOffer,cashRequest,propertiesRequest = action
yield self.handleTrade(playerId, otherAgentId,cashOffer,propertiesOffer,cashRequest,propertiesRequest)
actionCount+=1
if actionCount==0:
break
@inlineCallbacks
def handleTrade(self,agentId,otherAgentId,cashOffer,propertiesOffer,cashRequest,propertiesRequest):
previousPayload = self.state.getPhasePayload()
cashRequest = self.check_valid_cash(cashRequest)
cashOffer = self.check_valid_cash(cashOffer)
#Ask the other agent whether he accepts the trade.
phasePayload = [agentId,cashOffer,propertiesOffer,cashRequest,propertiesRequest]
self.state.setPhasePayload(phasePayload)
tradeResponse = yield self.runPlayerOnStateWithTimeout(otherAgentId,"RESPOND_TRADE")
print("TRADE", tradeResponse)
tradeResponse = self.typecast(tradeResponse, bool, False)
# if the trade was successful update the cash and property status
if tradeResponse:
currentPlayerCash = self.state.getCash(agentId)
otherPlayerCash = self.state.getCash(otherAgentId)
currentPlayerCash += (cashRequest - cashOffer)
otherPlayerCash += (cashOffer - cashRequest)
self.state.setCash(agentId,currentPlayerCash)
self.state.setCash(otherAgentId,otherPlayerCash)
for propertyRequest in propertiesRequest:
self.state.setPropertyOwner(propertyRequest,agentId)
for propertyOffer in propertiesOffer:
self.state.setPropertyOwner(propertyOffer,otherAgentId)
#Handle mortgaged properties that were involved in the trade after transferring ownership
mortgagedProperties = list(filter(lambda propertyId : self.state.isPropertyMortgaged(propertyId), propertiesOffer + propertiesRequest))
for mortgagedProperty in mortgagedProperties:
if mortgagedProperty not in self.mortgagedDuringTrade:
self.mortgagedDuringTrade.append(mortgagedProperty)
space = constants.board[mortgagedProperty]
propertyPrice = space['price']
mortgagedPrice = int(propertyPrice/2)
agentInQuestion = self.state.getPropertyOwner(mortgagedProperty)
agentsCash = self.state.getCash(agentInQuestion)
agentsCash -= int(mortgagedPrice*0.1)
self.state.setCash(agentInQuestion,agentsCash)
#Receive State
phasePayload = [tradeResponse,otherAgentId,cashOffer,propertiesOffer,cashRequest,propertiesRequest]
self.state.setPhasePayload(phasePayload)
yield self.runPlayerOnStateWithTimeout(agentId,"INFO")
self.state.setPhasePayload(previousPayload)
return True
# mortgageDuringTrade
# buy
# while there is no response from the one of the players keep querying
#
"""
Note : this is simulating real auction; commented for the time being
"""
# def start_auction(self):
# auctionedProperty = self.state.getPhasePayload()
# highestBid = 10
# currentParticipant = self.state.getCurrentPlayerId()
# auctionWinner = currentParticipant
# livePlayers = self.state.getLivePlayers()
# while len(livePlayers) > 1:
# currentParticipantIndex = livePlayers.index(currentParticipant)
# currentParticipant = livePlayers[(currentParticipantIndex + 1) % len(livePlayers)]
# currentBid = None
# if self.state.getCash(currentParticipant) > highestBid:
# phasePayload = [auctionedProperty,auctionWinner]
# ## NOTE: !!set additional payload if needed
# self.state.setPhase(self.PHASE_NUMBER_INDEX)
# self.state.setPhasePayload(phasePayload)
# currentBid = self.runPlayerOnStateWithTimeout(currentParticipant)
# if currentBid and currentBid > highestBid:
# highestBid = currentBid
# auctionWinner = currentParticipant
# else:
# # remove the current player
# # yes you could use livePlayers.remove(currentParticipant) trying to avoid mutation
# livePlayers = list(filter(lambda playerId : playerId != currentParticipant, livePlayers))
# auctionWinnerCurrentCash = self.state.getCash(auctionWinner)
# self.state.setCash(auctionWinner,auctionWinnerCurrentCash - highestBid)
# self.state.setPropertyOwner(auctionedProperty,auctionWinner)
# return [True, True]
class HandleJail
#
def subscribe()
class Auction
def __init__(self,state,nextAction):
state = {}
self.nextAction = nextAction
def publish():
pass
# decorator
def subscribe(self, agentId, aucionBid):
# logic
if self.state.agentsResponded.length === livePlayers:
#
self.nextAction(state)
class Trade
def __init__(self,state,nextAction):
state = {}
self.nextAction = nextAction
def publish():
pass
# decorator
def subscribe(self, agentId, aucionBid):
# logic
if self.state.agentsResponded === livePlayers:
self.nextAction(state)
class BuyConstructions
pass
class BuyProperty
def __init__(self,state,nextAction):
state = {}
self.nextAction = nextAction
def publish():
pass
# decorator
def subscribe(self, agentId, aucionBid):
# logic
if self.state.agentsResponded === livePlayers:
self.nextAction(state)
class SellConstructions
def __init__(self,state,nextAction):
state = {}
self.nextAction = nextAction
def publish():
pass
# decorator
def subscribe(self, agentId, aucionBid):
# logic
if self.state.agentsResponded === livePlayers:
self.nextAction(state)
class Mortgage
def __init__(self,state,nextAction):
state = {}
self.nextAction = nextAction
def publish():
pass
# decorator
def subscribe(self, agentId, aucionBid):
# logic
if self.state.agentsResponded === livePlayers:
self.nextAction(state)
def callingFunc():
auction = new Auction(state)
auction.publish()
# TODO:publis
def publishAuction(self):
self.publish("conduct_auction_{game_id}",state)
@subscribe("auctionResult")
def subscribeAuctionResult(self, agentId, auctionBid):
self.auctionRespondList.append(agentId)
currentPlayerId = self.state.getCurrentPlayerId()
livePlayers = self.state.getLivePlayers()
#By default, the player who started the auction would win and he would have to pay $1.
winner = currentPlayerId
winningBid = 1
for participant in livePlayers:
# asking for each participant for the bid
auctionBid = self.check_valid_cash(auctionBid)
playerCash = self.state.getCash(participant)
#Only if the player has enough money should his bid be considered valid
if auctionBid and auctionBid > winningBid and playerCash >= auctionBid:
winningBid = auctionBid
winner = participant
log("auction","Player "+str(winner)+" won the Auction")
playerCash = self.state.getCash(winner)
playerCash -= winningBid
self.state.setCash(winner,playerCash)
self.state.setPropertyOwner(auctionedProperty,winner)
#Receive State
phasePayload = [auctionedProperty,winner,winningBid]
self.state.setPhasePayload(phasePayload)
yield self.broadcastState()
"""
Accepts the actions of the blind auction from both players and performs it.
NOTE: The expected type of action is int. If the input is float, it will be typecast.
If the action is in some other type, following rules will be applied:
If opponent got the type of action wrong, current player wins.
else Opponent wins. i.e., opponent would win even if his action has incorrect type
as long as the current player also made a mistake in the type of his action
"""
@inlineCallbacks
def handle_auction(self,auctionedProperty):
currentPlayerId = self.state.getCurrentPlayerId()
livePlayers = self.state.getLivePlayers()
#By default, the player who started the auction would win and he would have to pay $1.
winner = currentPlayerId
winningBid = 1
for participant in livePlayers:
# asking for each participant for the bid
auctionBid = yield self.runPlayerOnStateWithTimeout(participant,"AUCTION")
auctionBid = self.check_valid_cash(auctionBid)
playerCash = self.state.getCash(participant)
#Only if the player has enough money should his bid be considered valid
if auctionBid and auctionBid > winningBid and playerCash >= auctionBid:
winningBid = auctionBid
winner = participant
log("auction","Player "+str(winner)+" won the Auction")
playerCash = self.state.getCash(winner)
playerCash -= winningBid
self.state.setCash(winner,playerCash)
self.state.setPropertyOwner(auctionedProperty,winner)
#Receive State
phasePayload = [auctionedProperty,winner,winningBid]
self.state.setPhasePayload(phasePayload)
yield self.broadcastState()
# [(1,4,2),(2,6,1),(3,8,1),(4,9,1)]
# Triple of playerId, propertyId, numberOfConstructions
def auctionInBSM(self,buyingDecisions,auctionEntity = "houses"):
"""
Bunch of small utitilies
"""
def updateBuyingDecisions(buyingDecisions,auctionWinner,propertySite):
def mapper(triple):
(playerId,propertyId,constructions) = triple
if playerId == auctionWinner and propertyId == propertySite:
return (playerId,propertyId,constructions - 1)
return (playerId,propertyId,constructions)
buyingDecisions = list(map(mapper, buyingDecisions))
return list(filter(lambda triple : triple[2] > 0,buyingDecisions))
def updateWinnerCash(auctionWinner, bidValue):
auctionWinnerCurrentCash = self.state.getCash(auctionWinner)
self.state.setCash(auctionWinner,auctionWinnerCurrentCash - bidValue)
def updateWinnerProperty(auctionedProperty):
currentConstructions = 4
if auctionEntity == "houses":
currentConstructions = self.state.getNumberOfHouses(auctionedProperty)
self.state.setNumberOfHouses(auctionedProperty, currentConstructions + 1)
def getConstructionsRemaining():
if auctionEntity == "houses":
return self.state.getHousesRemaining()
return self.state.getHotelsRemaining()
def transformBuyingDecisions():
# not doing any checks; to check if the the list is valid
def mapper(buyingDecision):
if auctionEntity == "houses":
return (buyingDecision[0],buyingDecision[1][0],buyingDecision[1][1])
return (buyingDecision[0], buyingDecision[1][0],1)
return list(map(mapper,buyingDecisions))
"""
End of Utilities;
Start of auction logic
"""
buyingDecisions = transformBuyingDecisions()
constructionsRemaining = getConstructionsRemaining()
while constructionsRemaining:
highestBid = min(list(map(lambda triple: self.state.getConstructionValue(triple[1]),buyingDecisions)))
interestedParticipants = list(set(map(lambda triple : triple[0], buyingDecisions)))
participantsCount = len(interestedParticipants)
#initializing
currentParticipantIndex = -1
currentParticipant = None
auctionWinner = None
propertySite = None
while True:
participationCount = len(interestedParticipants)
if participationCount < 2:
break
currentParticipantIndex = currentParticipantIndex % participationCount
currentParticipant = interestedParticipants[currentParticipantIndex]
# initization
currentBid = None
propertyId = None
if self.state.getCash(currentParticipant) > highestBid:
# Assuming a auction decison API
# set something and call some predefined state
# set phase index and payload
(currentBid,propertyId) = self.runPlayerOnState(currentParticipant)
if currentBid and currentBid > highestBid:
highestBid = currentBid
propertySite = propertyId
auctionWinner = currentParticipant
currentParticipantIndex +=1
else:
interestedParticipants.remove(currentParticipant)
buyingDecisions = updateBuyingDecisions(buyingDecisions,auctionWinner,propertySite)
constructionsRemaining -= 1
# update cash and property
updateWinnerCash(auctionWinner, highestBid)
updateWinnerProperty(auctionedProperty)
"""
(Q: Will there need to be a BSTM if the player receives money?)
Phase Properties:
Is the property owned?
If unowned, there are 3 sequential sub-phases: BSTM,Buying,Auction. Which one are you in?
If owned, 2 sub-phases: BSTM,rent. Note: BSTM here for opponent must be applied after the turn.
If cards, draw top card,do effect, return it to bottom of the deck.
If Go To Jail, send to jail. Immediately end the turn.
If currently in Jail, 3 ways to get out.
"""
"""
Incoming action format:
("R",) : represents rolling to get out
("P",) : represents paying $50 to get out (BSMT should follow)
("C", propertyNumber) : represents using a get out of jail card,
but in case someone has both, needs to specify which one they are using.
In general, should always specify the number (either 28 or 29)
Return values are 2 boolean values:
1. Whether the player is out of jail.
2. Whether there was a dice throw while handling jail state.
"""
def handle_in_jail_state(self,action):
currentPlayerId = self.state.getCurrentPlayerId()
if action=="R" or action=="P":
action = (action,)
if (isinstance(action, tuple) or isinstance(action, list)) and len(action)>0:
if action[0] == 'P':
playerCash = self.state.getCash(currentPlayerId)
#TODO: The player may not have enough money here. Is this the correct way to implement this?
if playerCash>=50:
self.state.setCash(currentPlayerId,playerCash-50)
else:
self.state.addDebtToBank(currentPlayerId,50)
self.state.setPosition(currentPlayerId,self.JUST_VISTING)
self.state.resetJailCounter(currentPlayerId)
return [True,False]
elif action[0] == 'C':
#Check if the player has the mentioned property card.
if (len(action)>1) & (action[1] in [self.CHANCE_GET_OUT_OF_JAIL_FREE,self.COMMUNITY_GET_OUT_OF_JAIL_FREE]):
if self.state.isPropertyOwned(action[1]) and self.state.rightOwner(currentPlayerId,action[1]):
if action[1] == self.COMMUNITY_GET_OUT_OF_JAIL_FREE:
self.chest.deck.append(constants.communityChestCards[4])
elif action[1] == self.CHANCE_GET_OUT_OF_JAIL_FREE:
self.chance.deck.append(constants.chanceCards[7])
self.state.setPropertyUnowned(action[1])
self.state.setPosition(currentPlayerId,self.JUST_VISTING)
self.state.resetJailCounter(currentPlayerId)
return [True,False]
"""If both the above method fail for some reason, we default to dice roll."""
diceThrow = None
if (self.diceThrows is not None) and len(self.diceThrows)>0:
diceThrow = self.diceThrows.pop(0)
self.dice.roll(dice=diceThrow)
if self.dice.double:
#Player can go out
#Need to ensure that there is no second turn for the player in this turn.
self.dice.double = False
self.state.setPosition(currentPlayerId,self.JUST_VISTING)
self.state.resetJailCounter(currentPlayerId)
return [True,True]
self.state.incrementJailCounter(currentPlayerId)
if self.state.getJailCounter(currentPlayerId)==3:
playerCash = self.state.getCash(currentPlayerId)
#The player has to pay $50 and get out.
#This is added as debt so that the player has the opportunity to resolve it.
self.state.addDebtToBank(currentPlayerId,50)
self.state.setPosition(currentPlayerId,self.JUST_VISTING)
self.state.resetJailCounter(currentPlayerId)
log("jail","Agent "+str(currentPlayerId)+" has been in jail for 3 turns. Forcing him to pay $50 to get out.")
return [True,True]
return [False,True]
"""
Returns 2 booleans
First is True if not in jail or no longer in jail
Second is True if dice has already been thrown for the current turn while determining if the player should be let out or remain in jail
"""
@inlineCallbacks
def handle_jail(self):
currentPlayerId = self.state.getCurrentPlayerId()
playerPosition = self.state.getPosition(currentPlayerId)
if playerPosition != self.JAIL:
return [True,False]
#InJail
self.state.setPhase(Phase.JAIL)
self.state.setPhasePayload(None)
action = yield self.runPlayerOnStateWithTimeout(currentPlayerId,"JAIL")
result = self.handle_in_jail_state(action)
phasePayload = [result[0]]
self.state.setPhasePayload(phasePayload)
#The player needs to know if he is still in jail or not.
yield self.broadcastState()
return result
def send_player_to_jail(self):
#Disable double
self.dice.double = False
currentPlayerId = self.state.getCurrentPlayerId()
log("jail","Agent "+str(currentPlayerId)+" has been sent to jail")
self.state.setPosition(currentPlayerId,self.JAIL)
self.state.setPhase(Phase.JAIL)
self.state.setPhasePayload(None)
"""
Dice Roll Function
1. Rolls the dice, checks for all the dice events.
2. Then moves the player to new position and finds out what the effect of the position is.
"""
def dice_roll(self,diceThrown):
currentPlayerId = self.state.getCurrentPlayerId()
playerPosition = self.state.getPosition(currentPlayerId)
playerCash = self.state.getCash(currentPlayerId)
if not diceThrown:
diceThrow = None
if (self.diceThrows is not None) and len(self.diceThrows)>0:
diceThrow = self.diceThrows.pop(0)
self.dice.roll(dice=diceThrow)
if self.dice.double_counter == 3:
self.send_player_to_jail()
return False
#End current player's turn here
#Should there be a GoToJail state to let the player know?
else:
#Update player position
playerPosition += (self.dice.die_1 + self.dice.die_2)
#Passing Go
if playerPosition>=self.BOARD_SIZE:
playerPosition = playerPosition % self.BOARD_SIZE
playerCash += self.PASSING_GO_MONEY
self.state.setCash(currentPlayerId,playerCash)
self.state.setPosition(currentPlayerId,playerPosition)
return True
def isProperty(self,position):
propertyClass = constants.board[position]['class']
return (propertyClass == 'Street') or (propertyClass == 'Railroad') or (propertyClass == 'Utility')
"""
Performed after dice is rolled and the player is moved to a new position.
Determines the effect of the position and action required from the player.
"""
@inlineCallbacks
def determine_position_effect(self):
currentPlayerId = self.state.getCurrentPlayerId()
playerPosition = self.state.getPosition(currentPlayerId)
playerCash = self.state.getCash(currentPlayerId)
turn_number = self.state.getTurn()
isProperty = self.isProperty(playerPosition)
if isProperty:
output = self.handle_property()
if 'phase' in output:
self.state.setPhase(output['phase'])
if 'phase_properties' in output:
self.state.setPhasePayload(output['phase_properties'])
if 'debt' in output:
self.state.setDebtToPlayer(currentPlayerId,output['debt'][0],output['debt'][1])
if self.state.getPhase()==Phase.BUYING:
action = yield self.runPlayerOnStateWithTimeout(currentPlayerId,"BUY")
action = self.typecast(action, bool, False)
if not action:
self.state.setPhase(Phase.AUCTION)
elif constants.board[playerPosition]['class'] == 'Chance':
#Chance
card = self.chance.draw_card()
log("cards","Chance card \""+str(card['content'])+"\" has been drawn")
#ReceiveState
phasePayload = card['id']
self.state.setPhase(Phase.CHANCE_CARD)
self.state.setPhasePayload(phasePayload)
yield self.broadcastState()
self.state.setPhase(Phase.NO_ACTION)
self.state.setPhasePayload(None)
self.handle_cards_pre_turn(card,'Chance')
elif constants.board[playerPosition]['class'] == 'Chest':
#Community
card = self.chest.draw_card()
log("cards","Community Chest card \""+str(card['content'])+"\" has been drawn")
#ReceiveState
phasePayload = card['id']
self.state.setPhase(Phase.COMMUNITY_CHEST_CARD)
self.state.setPhasePayload(phasePayload)
yield self.broadcastState()
self.state.setPhase(Phase.NO_ACTION)
self.state.setPhasePayload(None)
self.handle_cards_pre_turn(card,'Chest')
elif constants.board[playerPosition]['class'] == 'Tax':
#Tax
cash = constants.board[playerPosition]['tax']
self.state.setPhase(Phase.PAYMENT)
self.state.setPhasePayload(None)
self.state.addDebtToBank(currentPlayerId,cash)
elif constants.board[playerPosition]['class'] == 'GoToJail':
self.send_player_to_jail()
elif constants.board[playerPosition]['class'] == 'Idle':
#Represents Go,Jail(Visiting),Free Parking
pass
"""
Given that the current space is a property, determine what is to be done here.
This method can only be called for the current player during any given turn.
Hence only returns a 2 size tuple for debt.
"""
def handle_property(self):
currentPlayerId = self.state.getCurrentPlayerId()
playerPosition = self.state.getPosition(currentPlayerId)
playerCash = self.state.getCash(currentPlayerId)
isPropertyOwned = self.state.isPropertyOwned(playerPosition)
ownerId = self.state.getPropertyOwner(playerPosition)
output = {}
if not isPropertyOwned:
#Unowned
output['phase'] = Phase.BUYING
output['phase_properties'] = playerPosition
elif ownerId!=currentPlayerId:
space = constants.board[playerPosition]
monopolies = space['monopoly_group_elements']
counter = 1
for monopoly in monopolies:
if self.state.rightOwner(ownerId,monopoly):
counter += 1
rent = space['rent']
if (space['class'] == 'Street'):
if (counter==len(monopolies)+1):
rent = rent * 2
houseCount = self.state.getNumberOfHouses(playerPosition)
if houseCount==1:
rent = space['rent_house_1']
elif houseCount==2:
rent = space['rent_house_2']
elif houseCount==3:
rent = space['rent_house_3']
elif houseCount==4:
rent = space['rent_house_4']
elif houseCount==5:
rent = space['rent_hotel']
elif (space['class'] == 'Railroad'):
if counter == 2:
rent = 50
if counter == 3:
rent = 100
if counter == 4:
rent = 200
elif (space['class'] == 'Utility'):
if (counter==len(monopolies)+1):
rent = 10
rent = rent * (self.dice.die_1 + self.dice.die_2)
output['phase'] = Phase.PAYMENT
output['phase_properties'] = playerPosition
output['debt'] = (ownerId,rent)
else:
#When the property is owned by us
pass
return output
"""Method handles various events for Chance and Community cards"""
@inlineCallbacks
def handle_cards_pre_turn(self,card,deck):
currentPlayerId = self.state.getCurrentPlayerId()
playerPosition = self.state.getPosition(currentPlayerId)
playerCash = self.state.getCash(currentPlayerId)
phaseNumber = self.state.getPhase()
updateState = False
phasePayload = None
if card['type'] == 1:
#-ve represents you need to pay
if card['money']<0:
phaseNumber = Phase.PAYMENT
self.state.addDebtToBank(currentPlayerId,abs(card['money']))
else:
playerCash += abs(card['money'])
elif card['type'] == 2:
#-ve represents you need to pay
phaseNumber = Phase.PAYMENT
if card['money']<0:
debtAmount = abs(card['money'])
for playerId in self.PLAY_ORDER:
if playerId!=currentPlayerId and not self.state.hasPlayerLost(playerId):
self.state.setDebtToPlayer(currentPlayerId,playerId,debtAmount)
else:
debtAmount = abs(card['money'])
for playerId in self.PLAY_ORDER:
if playerId!=currentPlayerId and not self.state.hasPlayerLost(playerId):
self.state.setDebtToPlayer(playerId,currentPlayerId,debtAmount)
elif card['type'] == 3:
if card['position'] == self.JAIL:
#sending the player to jail
playerPosition = self.JAIL
self.send_player_to_jail()
else:
if (card['position'] - 1) < playerPosition:
#Passes Go
playerCash += self.PASSING_GO_MONEY
playerPosition = card['position'] - 1
updateState = True
elif card['type'] == 4:
"""Get out of Jail free"""
if deck == 'Chest':
propertyValue = self.COMMUNITY_GET_OUT_OF_JAIL_FREE
else:
propertyValue = self.CHANCE_GET_OUT_OF_JAIL_FREE
self.state.setPropertyOwner(propertyValue,currentPlayerId)
elif card['type'] == 5:
n_houses = 0
n_hotels = 0
for propertyId in range(self.BOARD_SIZE):
if self.state.rightOwner(currentPlayerId,propertyId):
housesCount = self.state.getNumberOfHouses(propertyId)
if housesCount==5:
n_hotels+=1
else:
n_houses+=housesCount
debtAmount = abs(card['money'])*n_houses + abs(card['money2'])*n_hotels
if debtAmount > 0:
phaseNumber = Phase.PAYMENT
self.state.addDebtToBank(currentPlayerId,debtAmount)
elif card['type'] == 6:
#Advance to nearest railroad. Pay 2x amount if owned
if (playerPosition < 5) or (playerPosition>=35):
if (playerPosition>=35):
#Passes Go
playerCash += self.PASSING_GO_MONEY
playerPosition = 5
elif (playerPosition < 15) and (playerPosition>=5):
playerPosition = 15
elif (playerPosition < 25) and (playerPosition>=15):
playerPosition = 25
elif (playerPosition < 35) and (playerPosition>=25):
playerPosition = 35
self.state.setPosition(currentPlayerId,playerPosition)
output = self.handle_property()
if 'phase' in output:
phaseNumber = output['phase']
if 'phase_properties' in output:
phasePayload = output['phase_properties']
if 'debt' in output:
#We need to double rent if the player landed on opponent's property.
self.state.setDebtToPlayer(currentPlayerId,output['debt'][0],output['debt'][1]*2)
elif card['type'] == 7:
#Advance to nearest utility. Pay 10x dice roll if owned
if (playerPosition < 12) or (playerPosition>=28):
if (playerPosition>=28):
#Passes Go
playerCash += self.PASSING_GO_MONEY
playerPosition = 12
elif (playerPosition < 28) and (playerPosition>=12):
playerPosition = 28
ownerId = self.state.getPropertyOwner(playerPosition)
if not self.state.isPropertyOwned(playerPosition):
#Unowned
phaseNumber = Phase.BUYING
phasePayload = playerPosition
elif ownerId!=currentPlayerId:
#Check if owned by opponent
diceThrow = None
if (self.diceThrows is not None) and len(self.diceThrows)>0:
diceThrow = self.diceThrows.pop(0)
self.dice.roll(ignore=True,dice=diceThrow)
phaseNumber = Phase.PAYMENT
self.state.setDebtToPlayer(currentPlayerId,ownerId,10 * (self.dice.die_1 + self.dice.die_2))
elif card['type'] == 8:
#Go back 3 spaces
playerPosition -= 3
updateState = True
else:
logger.info('Invalid card type {type}...'.format(type=card['type']))
self.state.setPosition(currentPlayerId,playerPosition)
self.state.setCash(currentPlayerId,playerCash)
self.state.setPhase(phaseNumber)
self.state.setPhasePayload(phasePayload)
if phaseNumber==Phase.BUYING:
action = yield self.runPlayerOnStateWithTimeout(currentPlayerId,"BUY")
action = self.typecast(action, bool, False)
if not action:
self.state.setPhase(Phase.AUCTION)
# make further calls
if updateState:
yield self.determine_position_effect()
"""
Handle the action response from the Agent for buying an unowned property
Only called for the currentPlayer during his turn.
"""
def handle_buy_property(self):
currentPlayerId = self.state.getCurrentPlayerId()
playerPosition = self.state.getPosition(currentPlayerId)
playerCash = self.state.getCash(currentPlayerId)
price = constants.board[playerPosition]['price']
if playerCash>=price:
self.state.setPropertyOwner(playerPosition,currentPlayerId)
self.state.setCash(currentPlayerId,playerCash-price)
log('buy',"Agent "+str(currentPlayerId)+" has bought "+constants.board[playerPosition]['name'])
#Clearing the payload as the buying has been completed
self.state.setPhasePayload(None)
return True
#This would indicate going to Auction
return False
"""
Handling payments the player has to make to the bank/opponent
Could be invoked for either player during any given turn.
Returns 2 boolean list - True if the player was able to pay off his debt
"""
def handle_payment(self):
for playerId in self.PLAY_ORDER:
if not self.state.hasPlayerLost(playerId):
self.state.clearDebt(playerId)
"""Function calls the relevant method of the Agent"""
def turn_effect(self):
currentPlayerId = self.state.getCurrentPlayerId()
phase = self.state.getPhase()
phasePayload = self.state.getPhasePayload()
if phase == Phase.BUYING:
self.handle_buy_property()
elif phase == Phase.AUCTION:
auctionedProperty = phasePayload
#
# self.publish(auctionedProperty)
turn_effect = yield self.handle_auction()
return turn_effect
"""
On final winner calculation, following are considered:
Player's cash,
Property value as on the title card,
House and Hotel purchase value,
Mortgaged properties at half price.
"""
def final_winning_condition(self):
agentCash = {}
agentPropertyWorth = {}
for playerId in self.PLAY_ORDER:
agentCash[playerId] = self.state.getCash(playerId)
agentPropertyWorth[playerId] = 0
for propertyId in range(40):
#In 0 to 39 board position range
isPropertyOwned = self.state.isPropertyOwned(propertyId)
ownerId = self.state.getPropertyOwner(propertyId)
houses = self.state.getNumberOfHouses(propertyId)
mortgaged = self.state.isPropertyMortgaged(propertyId)
price = constants.board[propertyId]['price']
build_cost = constants.board[propertyId]['build_cost']
if isPropertyOwned:
if mortgaged:
agentPropertyWorth[ownerId] += int(price/2)
else:
agentPropertyWorth[ownerId] += (price+build_cost*houses)
for propertyId in [self.CHANCE_GET_OUT_OF_JAIL_FREE,self.COMMUNITY_GET_OUT_OF_JAIL_FREE]:
isPropertyOwned = self.state.isPropertyOwned(propertyId)
ownerId = self.state.getPropertyOwner(propertyId)
if isPropertyOwned:
agentPropertyWorth[ownerId] += 50
#Gives the list of players sorted in descending order.
#Also takes into consideration if player lost earlier in the game.
#for playerId in self.PLAY_ORDER:
# log("win_condition","Agent "+str(playerId)+" Cash: "+str(agentCash[playerId]))
# log("win_condition","Agent "+str(playerId)+" Property Value: "+str(agentPropertyWorth[playerId]))
#def winnerSorting(playerId):
# if self.state.getTurnOfLoss(playerId)==-1:
# return self.TOTAL_NO_OF_TURNS+agentCash[playerId]+agentPropertyWorth[playerId]
# else:
# return self.state.getTurnOfLoss(playerId)
#return sorted(self.PLAY_ORDER,key=winnerSorting,reverse=True)
#Using an array here to handle ties
winners = []
highestAssets = 0
for playerId in self.PLAY_ORDER:
turn_of_loss = self.state.getTurnOfLoss(playerId)
if turn_of_loss==-1:
log("win_condition","Agent "+str(playerId)+" Cash: "+str(agentCash[playerId]))
log("win_condition","Agent "+str(playerId)+" Property Value: "+str(agentPropertyWorth[playerId]))
playerAssets = agentCash[playerId]+agentPropertyWorth[playerId]
if playerAssets > highestAssets:
winners = [playerId]
highestAssets = playerAssets
elif playerAssets == highestAssets:
winners.append(playerId)
else:
log("win_condition","Agent "+str(playerId)+" had lost in the turn: "+str(turn_of_loss))
return winners
def initialize_debug_state(self,diceThrows,chanceCards,communityCards):
if isinstance(diceThrows, list) and len(diceThrows)>0:
self.diceThrows = diceThrows
else:
self.diceThrows = diceThrows
if isinstance(chanceCards, list) and len(chanceCards)>0:
self.chance.reinit(constants.chanceCards,chanceCards)
if isinstance(communityCards, list) and len(communityCards)>0:
self.chest.reinit(constants.communityChestCards,communityCards)
@inlineCallbacks
def broadcastState(self):
for playerId in self.PLAY_ORDER:
yield self.runPlayerOnStateWithTimeout(playerId,"INFO")
"""
Function to be called to start the game.
Expects agents to be in the order of play.
"""
@inlineCallbacks
def runGame(self,agents,diceThrows=None,chanceCards=None,communityCards=None):
self.stateHistory = []
self.mortgagedDuringTrade = []
self.chest = Cards(constants.communityChestCards)
self.chance = Cards(constants.chanceCards)
#Stores the list of agents which are competing in the current game in the order of play.
self.agents = agents
self.PLAY_ORDER = agents #Stores the id's of all the players in the order of play
self.TOTAL_NO_OF_PLAYERS = len(self.agents)
self.dice = Dice()
self.state = State(self.PLAY_ORDER)
winner = None
#Setting an initial state. Used during testing.
#if isinstance(state,list) and len(state)==6:
# self.state = state
self.initialize_debug_state(diceThrows,chanceCards,communityCards)
# have we crossed the number of turns in a game
while (self.state.getTurn() < self.TOTAL_NO_OF_TURNS):
#
self.state.updateTurn()
playerId = self.state.getCurrentPlayerId()
if self.state.hasPlayerLost(playerId):
continue
self.dice.reset()
log("turn","Turn "+str(self.state.getTurn())+" start")
log("state","State at the start of the turn:")
log("state",self.state)
# pre dice roll
# update the turn and get the next player
# post dice roll
# everything else
while ( (self.diceThrows is None) or (len(self.diceThrows)>0) ):
self.state.setPhase(Phase.NO_ACTION)
self.state.setPhasePayload(None)
[outOfJail,diceThrown] = yield self.handle_jail()
if self.state.hasPlayerLost(playerId):
break
if outOfJail:
"""rolls dice, moves the player and determines what happens on the space he has fallen on."""
# dice roll
notInJail = self.dice_roll(diceThrown)
if self.state.hasPlayerLost(playerId):
break
if notInJail:
yield self.determine_position_effect()
if self.state.hasPlayerLost(playerId):
break
log("state","State after moving the player and updating state with effect of the position:")
log("state",self.state)
"""BSMT"""
self.mortgagedDuringTrade = []
previousPhase = self.state.getPhase()
previousPhasePayload = self.state.getPhasePayload()
self.state.setPhase(Phase.TRADE)
self.state.setPhasePayload(None)
self.conductBSM()
if self.state.hasPlayerLost(playerId):
break
yield self.conductTrade()
self.state.setPhase(previousPhase)
self.conductBSM()
if self.state.hasPlayerLost(playerId):
break
self.state.setPhasePayload(previousPhasePayload)
"""State now contain info about the position the player landed on"""
"""Performing the actual effect of the current position"""
yield self.turn_effect()
if self.state.hasPlayerLost(playerId):
break
self.handle_payment()
if self.state.hasPlayerLost(playerId):
break
log("state","State at the end of the turn:")
log("state",self.state)
if (not self.dice.double):
break
else:
log("dice","Rolled Doubles. Play again.")
log("turn","Turn "+str(self.state.getTurn())+" end")
"""Update the turn counter"""
lossCount = 0
for agentId in self.PLAY_ORDER:
if self.state.hasPlayerLost(agentId): lossCount+=1
if lossCount>=self.TOTAL_NO_OF_PLAYERS-1:
#Only one player left. Winner has been decided.
log("win","Only one player left.")
break
#TODO:
#Storing the state_history to log file
#f = open("state_history.log", "w")
#for history in self.stateHistory:
# f.write(str(history)+",\n")
"""Determine the winner"""
resultsArray = self.final_winning_condition()
if len(resultsArray)>1:
log("win","Agents "+str(resultsArray)+" won the Game.")
else:
log("win","Agent "+str(resultsArray[0])+" won the Game.")
self.state.setPhasePayload(None)
finalState = self.state.toJson()
#finalState = self.state
return [resultsArray,finalState]
"""
This function is called whenever adjudicator needs to communicate with the agent
The function to called on the agent is determined by reading the state.
All threading and signal based logic must go in here
"""
"""
Not sure the timning related thing works now; lets keep it on hold
"""
# @timeout_decorator.timeout(3000, timeout_exception=TimeoutError)
# def runPlayerOnStateWithTimeout(self, playerId,callType):
# try:
# return self.runPlayerOnState(playerId,callType)
# except TimeoutError:
# print("Agent Timed Out")
# """Change the return value here to ensure agent loses"""
# self.state.markPlayerLost(playerId,Reason.TIMEOUT)
# return None
@inlineCallbacks
def runPlayerOnStateWithTimeout(self,playerId,callType):
# player = self.getPlayer(playerId)
action = None
stateToBeSent = self.state.toJson()
# stateToBeSent = self.state
phaseProcedureMapping = {
"BSM" : "monopoly.agent{}.bsm",
"BUY" : "monopoly.agent{}.buy",
"AUCTION" : "monopoly.agent{}.auction",
"JAIL" : "monopoly.agent{}.jail",
"TRADE" : "monopoly.agent{}.trade",
"INFO" : "monopoly.agent{}.receivestate",
"RESPOND_TRADE" : "monopoly.agent{}.respondtrade"
}
procedure = phaseProcedureMapping[callType].format(str(playerId))
try:
action = yield self.call(procedure, stateToBeSent)
except:
print(procedure)
return action
if __name__ == '__main__':
import six
url = environ.get("CBURL", u"ws://127.0.0.1:8080/ws")
if six.PY2 and type(url) == six.binary_type:
url = url.decode('utf8')
realm = environ.get('CBREALM', u'realm1')
runner = ApplicationRunner(url, realm)
runner.run(Component)
# for testing purposes only
#adjudicator = Adjudicator()
#adjudicator.runGame(agentOne, agentTwo)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment