-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGame.py
129 lines (103 loc) · 4.11 KB
/
Game.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
from enum import Enum
import copy
import random
class Action(Enum):
Left = 0
Right = 1
Up = 2
Down = 3
class GameStatus(Enum):
Playing = 0
Won = 1
Lost = 2
class CellContent(Enum):
Player = 1
Goal = 2
Hole = 3
Empty = 4
class Pos:
def __init__(self, x, y):
self.m_X = x
self.m_Y = y
def __eq__(self, other):
if not other:
return False
return self.m_X == other.m_X and self.m_Y == other.m_Y
def __repr__(self):
return '[x=' + str(self.m_X) + ':y=' + str(self.m_Y) + ']'
class State:
m_Height = 4
m_Width = 3
def __init__(self, playerPos, goalPos, holePos):
self.m_GameStatus = GameStatus.Playing
self.ValidateInputPos([playerPos, goalPos, holePos])
self.m_PlayerPosition = playerPos
self.m_GoalPosition = goalPos
self.m_HolePosition = holePos
def ValidateInputPos(self, positions):
posTaken = list()
allPosUnique = not any(position in posTaken or posTaken.append(position) for position in positions)
if not allPosUnique:
raise ValueError('several input positions are identique. positions:' + str(positions))
def GetGrid(self):
grid = [[CellContent.Empty] * self.m_Width for _ in range(self.m_Height)]
grid[self.m_PlayerPosition.m_Y][self.m_PlayerPosition.m_X] = CellContent.Player
grid[self.m_GoalPosition.m_Y][self.m_GoalPosition.m_X] = CellContent.Goal
grid[self.m_HolePosition.m_Y][self.m_HolePosition.m_X] = CellContent.Hole
return grid
def PrintField(self, position):
if position == self.m_PlayerPosition:
return "X";
elif position == self.m_GoalPosition:
return "1"
elif position == self.m_HolePosition:
return "O"
else:
return "-"
def __repr__(self):
if self.m_GameStatus == GameStatus.Playing:
display = ''
for y in range(self.m_Height):
display += ' '.join(self.PrintField(Pos(x, y)) for x in range(self.m_Width))
display += '\n'
return display
else:
return self.m_GameStatus.name
def GetReward(self):
return {
GameStatus.Won: 10,
GameStatus.Lost: -10
}.get(self.m_GameStatus, -1)
def IsFinished(self):
return self.m_GameStatus == GameStatus.Won or self.m_GameStatus == GameStatus.Lost
def UpdatePos(self, action):
if action == Action.Left:
self.m_PlayerPosition.m_X = self.m_Width - 1 if self.m_PlayerPosition.m_X == 0 else self.m_PlayerPosition.m_X - 1
elif action == Action.Right:
self.m_PlayerPosition.m_X = (self.m_PlayerPosition.m_X + 1) % self.m_Width
elif action == Action.Up:
self.m_PlayerPosition.m_Y = self.m_Height - 1 if self.m_PlayerPosition.m_Y == 0 else self.m_PlayerPosition.m_Y - 1
else:
self.m_PlayerPosition.m_Y = (self.m_PlayerPosition.m_Y + 1) % self.m_Height
def UpdateGameStatus(self):
if self.m_PlayerPosition == self.m_GoalPosition:
self.m_GameStatus = GameStatus.Won
elif self.m_PlayerPosition == self.m_HolePosition:
self.m_GameStatus = GameStatus.Lost
def Move(self, action):
self.UpdatePos(action)
self.UpdateGameStatus()
return self
def Move(state, action):
nextState = copy.deepcopy(state)
return nextState.Move(action)
def GetAvailableRandomPos(takenPos):
while True:
pos = Pos(random.choice(range(State.m_Width)), random.choice(range(State.m_Height)))
if not any(p == pos for p in takenPos):
return pos
def CreateState(optionalPlayerPos, optionalGoalPos, optionalHolePos):
playerPos = optionalPlayerPos if optionalPlayerPos else GetAvailableRandomPos([optionalGoalPos, optionalHolePos])
goalPos = optionalGoalPos if optionalGoalPos else GetAvailableRandomPos([playerPos, optionalHolePos])
holePos = optionalHolePos if optionalHolePos else GetAvailableRandomPos([playerPos, goalPos])
return State(playerPos, goalPos, holePos)