Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Games
Kajongg
Commits
4cdb29e8
Commit
4cdb29e8
authored
Dec 16, 2017
by
Wolfgang Rohdewald
Browse files
use set comprehensions
this and the previous list comprehensions make scoringtest 2% faster
parent
5cf1c89b
Changes
15
Hide whitespace changes
Inline
Side-by-side
src/deferredutil.py
View file @
4cdb29e8
...
...
@@ -300,10 +300,10 @@ class DeferredBlock(StrMixin):
str
(
self
))
if
Debug
.
deferredBlock
:
commandText
=
[]
for
command
in
sorted
(
set
(
x
.
deferred
.
command
for
x
in
self
.
requests
)
):
for
command
in
sorted
(
{
x
.
deferred
.
command
for
x
in
self
.
requests
}
):
text
=
'%s:'
%
command
answerList
=
[]
for
answer
in
sorted
(
set
(
x
.
prettyAnswer
()
for
x
in
self
.
requests
if
x
.
deferred
.
command
==
command
)
):
for
answer
in
sorted
(
{
x
.
prettyAnswer
()
for
x
in
self
.
requests
if
x
.
deferred
.
command
==
command
}
):
answerList
.
append
((
answer
,
[
x
for
x
in
self
.
requests
if
x
.
deferred
.
command
==
command
and
answer
==
x
.
prettyAnswer
()]))
...
...
src/game.py
View file @
4cdb29e8
...
...
@@ -666,7 +666,7 @@ class Game:
# default value. If the server saved a score entry but our client
# did not, we get no record here. Should we try to fix this or
# exclude such a game from the list of resumable games?
if
len
(
set
(
x
[
4
]
for
x
in
qScoreRecords
)
)
!=
1
:
if
len
(
{
x
[
4
]
for
x
in
qScoreRecords
}
)
!=
1
:
logError
(
'game %d inconsistent: All score records for the same '
'hand must have the same prevailing wind'
%
gameid
)
...
...
@@ -1048,8 +1048,7 @@ class PlayingGame(Game):
for
tile
in
allTiles
:
assert
isinstance
(
tile
,
Tile
),
tile
# see https://www.logilab.org/ticket/23986
invisibleTiles
=
set
(
x
for
x
in
allTiles
if
x
not
in
self
.
visibleTiles
)
invisibleTiles
=
{
x
for
x
in
allTiles
if
x
not
in
self
.
visibleTiles
}
msg
=
i18n
(
'Short living wall: Tile is invisible, hence dangerous'
)
self
.
dangerousTiles
=
[
x
for
x
in
self
.
dangerousTiles
if
x
[
1
]
!=
msg
]
self
.
dangerousTiles
.
append
((
invisibleTiles
,
msg
))
...
...
src/hand.py
View file @
4cdb29e8
...
...
@@ -164,7 +164,7 @@ class Hand(StrMixin):
tileStrings
.
remove
(
part
)
self
.
values
=
tuple
(
x
.
value
for
x
in
self
.
tiles
)
self
.
suits
=
set
(
x
.
lowerGroup
for
x
in
self
.
tiles
)
self
.
suits
=
{
x
.
lowerGroup
for
x
in
self
.
tiles
}
self
.
declaredMelds
=
MeldList
(
x
for
x
in
self
.
melds
if
x
.
isDeclared
)
declaredTiles
=
list
(
sum
((
x
for
x
in
self
.
declaredMelds
),
[]))
self
.
tilesInHand
=
TileList
(
x
for
x
in
self
.
tiles
...
...
@@ -518,7 +518,7 @@ class Hand(StrMixin):
if
hand
.
won
:
result
.
append
(
hand
)
if
Debug
.
hand
:
_hiderules
=
', '
.
join
(
set
(
x
.
mjRule
.
name
for
x
in
result
)
)
_hiderules
=
', '
.
join
(
{
x
.
mjRule
.
name
for
x
in
result
}
)
if
_hiderules
:
self
.
debug
(
fmt
(
'Is calling {_hiderules}'
))
return
result
...
...
src/handboard.py
View file @
4cdb29e8
...
...
@@ -378,7 +378,7 @@ class PlayingHandBoard(HandBoard):
and
x
[
0
].
yoffset
==
yOld
and
x
[
1
]
and
x
[
1
].
yoffset
==
yNew
and
not
x
[
0
].
isBonus
]
for
element
in
set
(
x
[
1
].
tile
for
x
in
items
)
:
for
element
in
{
x
[
1
].
tile
for
x
in
items
}
:
items
=
[
x
for
x
in
movingPlaces
.
items
()
if
x
[
1
].
tile
is
element
]
if
len
(
items
)
>
1
:
...
...
src/humanclient.py
View file @
4cdb29e8
...
...
@@ -527,7 +527,7 @@ class HumanClient(Client):
for
ruleset
in
result
:
Ruleset
.
cached
(
ruleset
).
save
()
# make it known to the cache and save in db
return
tables
rulesetHashes
=
set
(
x
[
1
]
for
x
in
tables
)
rulesetHashes
=
{
x
[
1
]
for
x
in
tables
}
needRulesets
=
[
x
for
x
in
rulesetHashes
if
not
Ruleset
.
hashIsKnown
(
x
)]
if
needRulesets
:
self
.
callServer
(
...
...
src/kajonggtest.py
View file @
4cdb29e8
...
...
@@ -361,12 +361,12 @@ def removeInvalidCommits(csvFile):
if
not
os
.
path
.
exists
(
csvFile
):
return
rows
=
list
(
Csv
.
reader
(
csvFile
))
_
=
set
(
x
[
COMMITFIELD
]
for
x
in
rows
)
csvCommits
=
set
(
_
=
{
x
[
COMMITFIELD
]
for
x
in
rows
}
csvCommits
=
{
x
for
x
in
_
if
set
(
x
)
<=
set
(
'0123456789abcdef'
)
and
len
(
x
)
>=
7
)
x
)
>=
7
}
nonExisting
=
set
(
csvCommits
)
-
set
(
onlyExistingCommits
(
csvCommits
))
if
nonExisting
:
print
(
...
...
@@ -397,18 +397,18 @@ def readGames(csvFile):
if
not
allRowsGenerator
:
return
# we want unique tuples so we can work with sets
allRows
=
set
(
tuple
(
x
)
for
x
in
allRowsGenerator
)
allRows
=
{
tuple
(
x
)
for
x
in
allRowsGenerator
}
games
=
dict
()
# build set of rows for every ai
for
variant
in
set
(
tuple
(
x
[:
COMMITFIELD
])
for
x
in
allRows
)
:
for
variant
in
{
tuple
(
x
[:
COMMITFIELD
])
for
x
in
allRows
}
:
games
[
variant
]
=
frozenset
(
x
for
x
in
allRows
if
tuple
(
x
[:
COMMITFIELD
])
==
variant
)
return
games
def
hasDifferences
(
rows
):
"""True if rows have unwanted differences"""
return
(
len
(
set
(
tuple
(
list
(
x
)[
GAMEFIELD
:])
for
x
in
rows
)
)
>
len
(
set
(
tuple
(
list
(
x
)[:
COMMITFIELD
])
for
x
in
rows
)
))
return
(
len
(
{
tuple
(
list
(
x
)[
GAMEFIELD
:])
for
x
in
rows
}
)
>
len
(
{
tuple
(
list
(
x
)[:
COMMITFIELD
])
for
x
in
rows
}
))
def
firstDifference
(
rows
):
"""reduce to two rows showing a difference"""
...
...
@@ -467,13 +467,13 @@ def evaluate(games):
if
not
games
:
return
for
variant
,
rows
in
games
.
items
():
gameIds
=
set
(
x
[
GAMEFIELD
]
for
x
in
rows
)
if
len
(
gameIds
)
!=
len
(
set
(
tuple
(
list
(
x
)[
GAMEFIELD
:])
for
x
in
rows
)
):
gameIds
=
{
x
[
GAMEFIELD
]
for
x
in
rows
}
if
len
(
gameIds
)
!=
len
(
{
tuple
(
list
(
x
)[
GAMEFIELD
:])
for
x
in
rows
}
):
print
(
'ruleset "%s" AI "%s" has different rows for games'
%
(
variant
[
0
],
variant
[
1
]),
end
=
' '
)
for
game
in
sorted
(
gameIds
,
key
=
int
):
if
len
(
set
(
tuple
(
x
[
GAMEFIELD
:]
for
x
in
rows
if
x
[
GAMEFIELD
]
==
game
)
)
)
>
1
:
if
len
(
{
tuple
(
x
[
GAMEFIELD
:]
for
x
in
rows
if
x
[
GAMEFIELD
]
==
game
)
}
)
>
1
:
print
(
game
,
end
=
' '
)
print
()
break
...
...
src/meld.py
View file @
4cdb29e8
...
...
@@ -92,7 +92,7 @@ class Meld(TileList, StrMixin):
self
.
__setMeldType
()
self
.
isPungKong
=
self
.
isPung
or
self
.
isKong
self
.
isDeclared
=
self
.
isExposed
or
self
.
isKong
groups
=
set
(
x
.
group
.
lower
()
for
x
in
self
)
groups
=
{
x
.
group
.
lower
()
for
x
in
self
}
if
len
(
groups
)
==
1
:
self
.
group
=
self
[
0
].
group
self
.
lowerGroup
=
self
.
group
.
lower
()
...
...
@@ -268,16 +268,16 @@ class Meld(TileList, StrMixin):
self
.
isKong
=
True
return
if
len
(
tiles
)
==
3
and
length
==
3
:
if
len
(
set
(
x
.
value
for
x
in
tiles
)
)
==
1
:
if
len
(
{
x
.
value
for
x
in
tiles
}
)
==
1
:
if
self
.
case
in
(
'aaa'
,
'AAA'
):
if
len
(
set
(
x
.
group
for
x
in
tiles
)
)
==
3
:
if
len
(
{
x
.
group
for
x
in
tiles
}
)
==
3
:
if
all
(
x
.
lowerGroup
in
Tile
.
colors
for
x
in
tiles
):
self
.
isKnitted
=
True
return
groups
=
set
(
x
.
group
for
x
in
self
)
if
len
(
groups
)
>
2
or
len
(
set
(
x
.
lower
()
for
x
in
groups
)
)
>
1
:
groups
=
{
x
.
group
for
x
in
self
}
if
len
(
groups
)
>
2
or
len
(
{
x
.
lower
()
for
x
in
groups
}
)
>
1
:
raise
UserWarning
(
'Meld %s is malformed'
%
self
)
values
=
set
(
x
.
value
for
x
in
self
)
values
=
{
x
.
value
for
x
in
self
}
if
length
==
4
:
if
len
(
values
)
>
1
:
raise
UserWarning
(
'Meld %s is malformed'
%
self
)
...
...
src/player.py
View file @
4cdb29e8
...
...
@@ -91,7 +91,7 @@ class Players(list, StrMixin):
def
translatePlayerNames
(
self
,
names
):
"""for a list of names, translates those names which are english
player names into the local language"""
known
=
set
(
x
.
name
for
x
in
self
)
known
=
{
x
.
name
for
x
in
self
}
return
[
self
.
byName
(
x
).
localName
if
x
in
known
else
x
for
x
in
names
]
...
...
@@ -812,11 +812,11 @@ class PlayingPlayer(Player):
dragonsDangerous
=
dragonsDangerous
or
dragonMelds
>=
2
if
windsDangerous
:
dangerous
.
append
(
(
set
(
x
for
x
in
elements
.
winds
if
x
not
in
self
.
visibleTiles
)
,
(
{
x
for
x
in
elements
.
winds
if
x
not
in
self
.
visibleTiles
}
,
i18n
(
'Player %1 exposed many winds'
,
pName
)))
if
dragonsDangerous
:
dangerous
.
append
(
(
set
(
x
for
x
in
elements
.
dragons
if
x
not
in
self
.
visibleTiles
)
,
(
{
x
for
x
in
elements
.
dragons
if
x
not
in
self
.
visibleTiles
}
,
i18n
(
'Player %1 exposed many dragons'
,
pName
)))
self
.
dangerousTiles
=
dangerous
if
dangerous
and
Debug
.
dangerousGame
:
...
...
src/rule.py
View file @
4cdb29e8
...
...
@@ -433,8 +433,8 @@ into a situation where you have to pay a penalty"""))
self
.
loadRules
()
self
.
__setParametersFrom
(
self
)
for
ruleList
in
self
.
ruleLists
:
assert
len
(
ruleList
)
==
len
(
set
(
x
.
key
()
for
x
in
ruleList
)
),
'%s has non-unique key'
%
ruleList
.
name
assert
len
(
ruleList
)
==
len
(
{
x
.
key
()
for
x
in
ruleList
}
),
'%s has non-unique key'
%
ruleList
.
name
for
rule
in
ruleList
:
if
hasattr
(
rule
,
'score'
):
rule
.
score
.
ruleset
=
self
...
...
src/rulecode.py
View file @
4cdb29e8
...
...
@@ -437,9 +437,9 @@ class StandardMahJongg(MJRule):
if
len
(
valueSet
)
==
1
:
# no chow reachable, only pair/pung
continue
singles
=
set
(
x
for
x
in
valueSet
if
values
.
count
(
x
)
==
1
and
not
set
([
x
-
1
,
x
-
2
,
x
+
1
,
x
+
2
])
&
valueSet
)
singles
=
{
x
for
x
in
valueSet
if
values
.
count
(
x
)
==
1
and
not
set
([
x
-
1
,
x
-
2
,
x
+
1
,
x
+
2
])
&
valueSet
}
isolated
+=
len
(
singles
)
if
isolated
>
1
:
# this is not a calling hand
...
...
@@ -503,7 +503,7 @@ class WrigglingSnake(MJRule):
def
shouldTry
(
hand
,
maxMissing
=
3
):
if
hand
.
declaredMelds
:
return
False
return
(
len
(
set
(
x
.
exposed
for
x
in
hand
.
tiles
)
)
+
maxMissing
>
12
return
(
len
(
{
x
.
exposed
for
x
in
hand
.
tiles
}
)
+
maxMissing
>
12
and
all
(
not
x
.
isChow
for
x
in
hand
.
declaredMelds
))
def
computeLastMelds
(
hand
):
...
...
@@ -606,7 +606,7 @@ class TripleKnitting(MJRule):
while
len
(
rest
)
>=
2
:
for
tile
in
sorted
(
set
(
rest
)):
value
=
tile
.
value
suits
=
set
(
x
.
group
for
x
in
rest
if
x
.
value
==
value
)
suits
=
{
x
.
group
for
x
in
rest
if
x
.
value
==
value
}
if
len
(
suits
)
<
2
:
yield
tuple
(
melds
),
tuple
(
rest
)
return
...
...
@@ -899,7 +899,7 @@ class FourBlessingsHoveringOverTheDoor(RuleCode):
class
AllGreen
(
RuleCode
):
def
appliesToHand
(
hand
):
return
set
(
x
.
exposed
for
x
in
hand
.
tiles
)
<
elements
.
greenHandTiles
return
{
x
.
exposed
for
x
in
hand
.
tiles
}
<
elements
.
greenHandTiles
class
LastTileFromWall
(
RuleCode
):
...
...
@@ -1146,7 +1146,7 @@ class ThirteenOrphans(MJRule):
return
result
def
appliesToHand
(
hand
):
return
set
(
x
.
exposed
for
x
in
hand
.
tiles
)
==
elements
.
majors
return
{
x
.
exposed
for
x
in
hand
.
tiles
}
==
elements
.
majors
def
winningTileCandidates
(
cls
,
hand
):
if
any
(
x
in
hand
.
values
for
x
in
Tile
.
minors
):
...
...
@@ -1154,7 +1154,7 @@ class ThirteenOrphans(MJRule):
return
set
()
if
not
cls
.
shouldTry
(
hand
,
1
):
return
set
()
handTiles
=
set
(
x
.
exposed
for
x
in
hand
.
tiles
)
handTiles
=
{
x
.
exposed
for
x
in
hand
.
tiles
}
missing
=
elements
.
majors
-
handTiles
if
not
missing
:
# if all 13 tiles are there, we need any one of them:
...
...
@@ -1166,7 +1166,7 @@ class ThirteenOrphans(MJRule):
# TODO: look at how many tiles there still are on the wall
if
hand
.
declaredMelds
:
return
False
handTiles
=
set
(
x
.
exposed
for
x
in
hand
.
tiles
)
handTiles
=
{
x
.
exposed
for
x
in
hand
.
tiles
}
missing
=
elements
.
majors
-
handTiles
if
len
(
missing
)
>
maxMissing
:
return
False
...
...
@@ -1179,7 +1179,7 @@ class ThirteenOrphans(MJRule):
hand
=
candidates
.
hand
if
not
cls
.
shouldTry
(
hand
):
return
candidates
handTiles
=
set
(
x
.
exposed
for
x
in
hand
.
tiles
)
handTiles
=
{
x
.
exposed
for
x
in
hand
.
tiles
}
missing
=
elements
.
majors
-
handTiles
havePair
=
False
keep
=
(
6
-
len
(
missing
))
*
5
...
...
src/scoring.py
View file @
4cdb29e8
...
...
@@ -92,7 +92,7 @@ class SelectPlayers(SelectRuleset):
def
__selectedNames
(
self
):
"""A set with the currently selected names"""
return
set
(
cbName
.
currentText
()
for
cbName
in
self
.
nameWidgets
)
return
{
cbName
.
currentText
()
for
cbName
in
self
.
nameWidgets
}
def
slotValidate
(
self
):
"""try to find 4 different players and update status of the Ok button"""
...
...
src/scoringtest.py
View file @
4cdb29e8
...
...
@@ -121,7 +121,7 @@ class Helpers:
game
.
players
[
0
].
clearCache
()
hand
=
Hand
(
game
.
players
[
0
],
string
)
testSays
=
TileList
(
set
(
x
.
lastTile
.
exposed
for
x
in
hand
.
callingHands
)
).
sorted
()
{
x
.
lastTile
.
exposed
for
x
in
hand
.
callingHands
}
).
sorted
()
if
isinstance
(
expected
,
list
):
if
idx
>=
len
(
expected
):
idx
%=
len
(
RULESETS
)
//
2
...
...
src/server.py
View file @
4cdb29e8
...
...
@@ -223,7 +223,7 @@ class MJServer:
def
generateTableId
(
self
):
"""generates a new table id: the first free one"""
usedIds
=
set
(
self
.
tables
or
[
0
])
availableIds
=
set
(
x
for
x
in
range
(
1
,
2
+
max
(
usedIds
))
)
availableIds
=
{
x
for
x
in
range
(
1
,
2
+
max
(
usedIds
))
}
return
min
(
availableIds
-
usedIds
)
def
newTable
(
self
,
user
,
ruleset
,
playOpen
,
...
...
src/tables.py
View file @
4cdb29e8
...
...
@@ -386,7 +386,7 @@ class TableList(QWidget):
if
self
.
view
.
model
():
chatWindows
=
dict
((
x
.
tableid
,
x
.
chatWindow
)
for
x
in
self
.
view
.
model
().
tables
)
unusedWindows
=
set
(
x
.
chatWindow
for
x
in
self
.
view
.
model
().
tables
)
unusedWindows
=
{
x
.
chatWindow
for
x
in
self
.
view
.
model
().
tables
}
for
table
in
tables
:
table
.
chatWindow
=
chatWindows
.
get
(
table
.
tableid
,
None
)
unusedWindows
-=
set
([
table
.
chatWindow
])
...
...
@@ -409,8 +409,8 @@ class TableList(QWidget):
self
.
requestedNewTable
=
False
model
=
self
.
view
.
model
()
if
model
:
oldIds
=
set
(
x
.
tableid
for
x
in
model
.
tables
)
newIds
=
sorted
(
list
(
set
(
x
.
tableid
for
x
in
tables
)
-
oldIds
)
)
oldIds
=
{
x
.
tableid
for
x
in
model
.
tables
}
newIds
=
sorted
(
{
x
.
tableid
for
x
in
tables
}
-
oldIds
)
if
newIds
:
return
newIds
[
0
]
if
self
.
selectedTable
():
...
...
src/tile.py
View file @
4cdb29e8
...
...
@@ -123,7 +123,7 @@ class Tile(str, StrMixin):
cls
.
cache
[
key
]
=
result
existing
=
list
([
x
for
x
in
cls
.
cache
.
values
()
if
x
.
key
==
result
.
key
])
existingIds
=
set
(
id
(
x
)
for
x
in
existing
)
existingIds
=
{
id
(
x
)
for
x
in
existing
}
assert
len
(
existingIds
)
==
1
,
'new is:{} existing are: {} with ids {}'
.
format
(
result
,
existing
,
existingIds
)
result
.
exposed
=
result
.
concealed
=
result
.
swapped
=
None
...
...
@@ -270,7 +270,7 @@ class TileList(list):
if
tile
.
lowerGroup
not
in
Tile
.
colors
:
return
[]
group
=
tile
.
group
values
=
set
(
x
.
value
for
x
in
self
if
x
.
group
==
group
)
values
=
{
x
.
value
for
x
in
self
if
x
.
group
==
group
}
chows
=
[]
for
offsets
in
[(
0
,
1
,
2
),
(
-
2
,
-
1
,
0
),
(
-
1
,
0
,
1
)]:
subset
=
set
([
tile
.
value
+
x
for
x
in
offsets
])
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment