polish robot creation, add shared game launching!!!
This commit is contained in:
parent
10edbacf86
commit
6f5e58e777
|
@ -238,6 +238,13 @@ class Pos(object):
|
|||
def Right(self):
|
||||
cdef PosI posI = self.i
|
||||
return posI.Right()
|
||||
def Clone(self):
|
||||
cdef PosI posI = self.i
|
||||
return posI.ToPos()
|
||||
def Equals(self, other):
|
||||
cdef PosI posIL = self.i
|
||||
cdef PosI posIR = other.i
|
||||
return posIL.xz == posIR.xz and posIL.yz == posIR.yz and posIL.w == posIR.w and posIL.h == posIR.h
|
||||
def __setstate__(self, state):
|
||||
self.i = PosI(state["w"], state["h"], state["xz"] + 1, state["yz"] + 1)
|
||||
def __getstate__(self):
|
||||
|
|
31
basetoken.py
31
basetoken.py
|
@ -411,6 +411,33 @@ class MiButton(MiStatic):
|
|||
def Value(self):
|
||||
return self.value
|
||||
|
||||
class MiButtonConfirm(MiButton):
|
||||
def InitPersistent(self, stName, stConfirm, dgCmd):
|
||||
super(MiButtonConfirm, self).InitPersistent(stName, dgCmd)
|
||||
self.stConfirm = stConfirm
|
||||
self.fConfirming = False
|
||||
|
||||
def StName(self):
|
||||
if self.fConfirming:
|
||||
return self.stConfirm
|
||||
return super(MiButtonConfirm, self).StName()
|
||||
|
||||
def HandleKey(self, key):
|
||||
if ansi.FEnter(key) or key == ' ':
|
||||
if self.fConfirming:
|
||||
self.Exec()
|
||||
else:
|
||||
self.fConfirming = True
|
||||
return True
|
||||
else:
|
||||
self.fConfirming = False
|
||||
return False
|
||||
|
||||
def ColBg(self, selor):
|
||||
if self.fConfirming:
|
||||
return ansi.RED
|
||||
return super(MiButtonConfirm, self).ColBg(selor)
|
||||
|
||||
class MiToggle(MiButton):
|
||||
def InitPersistent(self, stName, fInitial = False):
|
||||
MiButton.InitPersistent(self, stName, None, fInitial)
|
||||
|
@ -802,7 +829,7 @@ class OvStatic(TokenClient):
|
|||
class OvMenu(OvStatic):
|
||||
def run(self):
|
||||
while True:
|
||||
self.miMenu.HandleKey(self.client.EvKey(self.game).receive(self))
|
||||
self.miMenu.HandleKey(self.EvKey().receive(self))
|
||||
|
||||
def draw(self, ascr, client):
|
||||
self.drawI(ascr, client, True)
|
||||
|
@ -819,7 +846,7 @@ class OvPopup(OvStatic):
|
|||
self.evShow.receive(self)
|
||||
self.fAwake = True
|
||||
while self.fAwake:
|
||||
key = self.client.EvKey(self.game).receive(self)
|
||||
key = self.EvKey().receive(self)
|
||||
if not self.miMenu.HandleKey(key):
|
||||
if key == ansi.K_TAB or key == ansi.K_DEL or key == ' ' or ansi.FEnter(key):
|
||||
self.fAwake = False
|
||||
|
|
|
@ -625,3 +625,9 @@ class TokenClient(Token):
|
|||
|
||||
def FPersist(self):
|
||||
return False
|
||||
|
||||
def Cldg(self):
|
||||
return self.game.GetCldg(self.client)
|
||||
|
||||
def EvKey(self):
|
||||
return self.client.EvKey(self.game)
|
||||
|
|
34
scripting.py
34
scripting.py
|
@ -18,6 +18,8 @@ from basetoken import *
|
|||
from tpers import *
|
||||
from util import *
|
||||
from contextlib import contextmanager
|
||||
import itertools
|
||||
import random
|
||||
|
||||
# sobj -- generic hungarian for any object that is usable in scripts
|
||||
# stmt -- statement; a synt that can be used as a line in a SyntBlock
|
||||
|
@ -42,9 +44,17 @@ class Flagdef(TPrs):
|
|||
class Rbot(TPrs):
|
||||
def InitPersistent(self, botdef):
|
||||
self.botdef = botdef
|
||||
self.x = botdef.x
|
||||
self.y = botdef.y
|
||||
self.pos = ansi.Pos(x=botdef.x, y=botdef.y)
|
||||
|
||||
def Ach(self):
|
||||
return self.botdef.ach
|
||||
|
||||
def Pos(self):
|
||||
return self.pos
|
||||
|
||||
def Move(self, pos):
|
||||
self.pos = pos
|
||||
|
||||
class Defs(TPrs):
|
||||
def InitPersistent(self, rgflagdef = None, rgbotdef = None):
|
||||
self.rgflagdef = rgflagdef or []
|
||||
|
@ -57,12 +67,28 @@ class Vm(TPrs):
|
|||
def InitPersistent(self, defs):
|
||||
self.defs = defs
|
||||
self.mpflagdef = { flagdef: flagdef.value for flagdef in defs.rgflagdef }
|
||||
self.mpbotdef = { botdef: Rbot(botdef) for botdef in defs.rgbotdef }
|
||||
self.mpbotdef = { botdef: Rbot(botdef) for botdef in defs.rgbotdef if not botdef.fPlayer }
|
||||
self.rgrbotPlayer = []
|
||||
|
||||
def SetFlag(self, flagdef, fValue):
|
||||
self.mpflagdef[flagdef] = fValue
|
||||
|
||||
def FFlagSet(self, flagdef):
|
||||
return self.mpflagdef[flagdef]
|
||||
|
||||
def AddPlayer(self):
|
||||
rgbotdefPlayer = [botdef for botdef in self.defs.rgbotdef if botdef.fPlayer]
|
||||
botdef = random.choice(rgbotdefPlayer)
|
||||
rbotPlayer = Rbot(botdef)
|
||||
self.rgrbotPlayer.append(rbotPlayer)
|
||||
return rbotPlayer
|
||||
|
||||
def RemovePlayer(self, rbotPlayer):
|
||||
self.rgrbotPlayer.remove(rbotPlayer)
|
||||
|
||||
def Rgrbot(self):
|
||||
return itertools.chain(self.mpbotdef.values(), self.rgrbotPlayer)
|
||||
|
||||
def Fail(self, stMessage, synt):
|
||||
self.Log(Fail(stMessage, synt))
|
||||
|
||||
|
@ -883,7 +909,7 @@ class Pov(TokenClient):
|
|||
|
||||
def run(self):
|
||||
while True:
|
||||
key = self.client.EvKey(self.game).receive(self)
|
||||
key = self.EvKey().receive(self)
|
||||
if key == ansi.K_PGDN:
|
||||
self.block.Eval(Vm(self.defs))
|
||||
psel = self.pselstate.PselByClient(self.client)
|
||||
|
|
194
whiteboard.py
194
whiteboard.py
|
@ -20,7 +20,7 @@ from basetoken import *
|
|||
from tpers import *
|
||||
from datetime import *
|
||||
from util import *
|
||||
from scripting import Botdef, Flagdef, Defs, PselState, Pov
|
||||
from scripting import Botdef, Flagdef, Defs, PselState, Pov, Vm
|
||||
import telnet
|
||||
import time
|
||||
import login
|
||||
|
@ -129,7 +129,10 @@ class Drawing(Ownable):
|
|||
|
||||
def SetTimestamp(self):
|
||||
self.dtLastModified = datetime.now()
|
||||
|
||||
|
||||
def FPlayable(self):
|
||||
return False
|
||||
|
||||
@Version(4)
|
||||
class Board(Drawing):
|
||||
def InitPersistent(self, owner, stName, user, rglayer=None, dtLastModified=None):
|
||||
|
@ -142,13 +145,21 @@ class Board(Drawing):
|
|||
def W(self): return config.W
|
||||
def H(self): return config.H
|
||||
|
||||
def FPlayable(self):
|
||||
return len([botdef for botdef in self.defs.rgbotdef if botdef.fPlayer]) > 0
|
||||
|
||||
def draw(self, ascr):
|
||||
for layer in reversed(self.rglayer):
|
||||
ascr.PutAscr(layer.ascr)
|
||||
|
||||
def DrawObjectDefs(self, ascr):
|
||||
def DrawObjectDefs(self, ascr, bgColor = None):
|
||||
for botdef in self.defs.rgbotdef:
|
||||
ascr.PutAch(botdef.ach, botdef.x, botdef.y)
|
||||
ach = botdef.ach
|
||||
if bgColor != None:
|
||||
oach = ansi.Ach(ach)
|
||||
oach.bgCol = bgColor
|
||||
ach = oach.ToAch()
|
||||
ascr.PutAch(ach, botdef.x, botdef.y)
|
||||
|
||||
def Save(self):
|
||||
fn = config.DIR_ANSI + "/" + "_".join([str(x) for x in time.localtime()])
|
||||
|
@ -172,6 +183,14 @@ class Board(Drawing):
|
|||
self.defs = Defs()
|
||||
self.layerObj = self.rglayer[0]
|
||||
|
||||
def LayerObj(self):
|
||||
return self.layerObj
|
||||
|
||||
def AchAtPos(self, pos, layer = None):
|
||||
if layer == None:
|
||||
layer = self.LayerObj()
|
||||
return layer.ascr.GetAch(pos.X(), pos.Y())
|
||||
|
||||
class Sprite(Drawing):
|
||||
def InitPersistent(self, owner, stName, user, w, h):
|
||||
self.w = w
|
||||
|
@ -346,15 +365,15 @@ class Cursor(TokenClient):
|
|||
self.ovStatus = OvStatic(self, self.client, miStatus, OvStatic.BOTTOM)
|
||||
|
||||
def StLayerName(self, layer):
|
||||
return ('[Bot] ' if layer == self.game.drawing.layerObj else '') + layer.StName()
|
||||
return ('[Bot] ' if layer == self.game.drawing.LayerObj() else '') + layer.StName()
|
||||
|
||||
def StStatus(self):
|
||||
stStatus = "<Tab>: Menu"
|
||||
if self.GetLayer() == self.game.drawing.layerObj:
|
||||
if self.GetLayer() == self.game.drawing.LayerObj():
|
||||
botdef = self.BotdefAtPos(self.pos)
|
||||
if botdef:
|
||||
stStatus += " | <Enter>: Edit bot"
|
||||
elif self.game.drawing.layerObj.ascr.GetAch(self.pos.X(), self.pos.Y()) != ansi.achBlank:
|
||||
elif self.game.drawing.AchAtPos(self.pos) != ansi.achBlank:
|
||||
stStatus += " | <Enter>: Make bot"
|
||||
return stStatus
|
||||
|
||||
|
@ -432,7 +451,7 @@ class Cursor(TokenClient):
|
|||
def run(self):
|
||||
with self.game.drawing.chat.evChat.oob(self, self.OnChat):
|
||||
while True:
|
||||
key = self.client.EvKey(self.game).receive(self)
|
||||
key = self.EvKey().receive(self)
|
||||
fDontBlink = True
|
||||
if key == ansi.K_LEFT:
|
||||
self.pos.Left()
|
||||
|
@ -510,26 +529,26 @@ class Cursor(TokenClient):
|
|||
return self.fBlink or self.cDontBlink > 0
|
||||
|
||||
def EditBot(self):
|
||||
if self.GetLayer() == self.game.drawing.layerObj:
|
||||
if self.GetLayer() == self.game.drawing.LayerObj():
|
||||
botdef = self.BotdefAtPos(self.pos)
|
||||
ach = self.game.drawing.layerObj.ascr.GetAch(self.pos.X(), self.pos.Y())
|
||||
ach = self.game.drawing.AchAtPos(self.pos)
|
||||
fNewBot = ach != ansi.achBlank if not botdef else False
|
||||
if not fNewBot and not botdef:
|
||||
return
|
||||
if fNewBot:
|
||||
botdef = Botdef('Bot ' + str(len(self.game.drawing.defs.rgbotdef) + 1) + ' (' + ansi.Ach(ach).ch + ')', ach, self.pos.X(), self.pos.Y())
|
||||
self.game.drawing.defs.rgbotdef.append(botdef)
|
||||
|
||||
evDone = Event(self.game)
|
||||
def DgDone(val):
|
||||
return lambda: evDone.fire(val)
|
||||
|
||||
|
||||
miBotName = MiTypein(None, "BotName", 80)
|
||||
miBotName.SetValue(botdef.stName)
|
||||
miMenu = MiMenu([None,
|
||||
MiStatic("Bot Name"), miBotName, None,
|
||||
MiToggle("Is Player", botdef.fPlayer), None,
|
||||
MiButton("Save", DgDone(True)), MiButton("Cancel", DgDone(False)), None,
|
||||
MiButton("Edit Code (live)", lambda: self.client.joinGame(self.game.GameSyntEdit(botdef.syntOnTouch))), None])
|
||||
MiStatic("Bot Name"), miBotName,
|
||||
MiToggle("Is Player", botdef.fPlayer),
|
||||
MiButton("Edit Code (live)", lambda: self.client.joinGame(self.game.GameSyntEdit(botdef.syntOnTouch))), None,
|
||||
MiButton("Save", lambda: evDone.fire(True)), None, None,
|
||||
MiButtonConfirm("Delete", "Hit RETURN again to confirm!", lambda: evDone.fire(False)), None])
|
||||
|
||||
ov = OvMenu(self, self.client, miMenu, OvMenu.MIDDLE)
|
||||
try:
|
||||
|
@ -539,10 +558,8 @@ class Cursor(TokenClient):
|
|||
if result:
|
||||
botdef.stName = miBotName.Value()
|
||||
botdef.fPlayer = miMenu.MiByName("Is Player").Value()
|
||||
if fNewBot:
|
||||
self.game.drawing.defs.rgbotdef.append(botdef)
|
||||
|
||||
|
||||
else:
|
||||
self.game.drawing.defs.rgbotdef.remove(botdef)
|
||||
|
||||
def draw(self, ascr, client):
|
||||
if self.FDrawCursor():
|
||||
|
@ -553,7 +570,7 @@ class Cursor(TokenClient):
|
|||
chCursor = chr(177)
|
||||
self.Put(chCursor, ascr, *self.XzYzScreenPic())
|
||||
elif self.fBlink:
|
||||
self.Put(str(self.client.Cldg(self.game).iclient)[0], ascr, *self.XzYzScreenPic())
|
||||
self.Put(str(self.Cldg().iclient)[0], ascr, *self.XzYzScreenPic())
|
||||
|
||||
class CursorSprite(Cursor):
|
||||
def InitPersistent(self, game, client):
|
||||
|
@ -595,20 +612,28 @@ class CursorSprite(Cursor):
|
|||
if self.blinkerAnimate:
|
||||
return False
|
||||
return Cursor.FDrawCursor(self)
|
||||
|
||||
class WhiteboardDraw(TokenClient):
|
||||
def InitPersistent(self, owner, client):
|
||||
TokenClient.InitPersistent(self, owner, client, "drawable", "solid")
|
||||
TokenClient.InitPersistent(self, owner, client, "drawable", "solid", "cursor")
|
||||
self.color = 0
|
||||
self.fBlink = False
|
||||
|
||||
def draw(self, ascr, client):
|
||||
if client == self.client:
|
||||
fDrawObjects = True
|
||||
if self.owner.miLayers.Value("Show One"):
|
||||
ascr.PutAscr(self.owner.GetLayer().ascr)
|
||||
fDrawObjects = self.owner.GetLayer() == self.owner.layerObj
|
||||
fDrawObjects = self.owner.GetLayer() == self.owner.LayerObj()
|
||||
else:
|
||||
self.game.drawing.draw(ascr)
|
||||
if fDrawObjects:
|
||||
self.game.drawing.DrawObjectDefs(ascr)
|
||||
self.game.drawing.DrawObjectDefs(ascr, self.color if not self.fBlink else None)
|
||||
|
||||
def blinkCursor(self, fBlink):
|
||||
self.fBlink = fBlink
|
||||
if fBlink:
|
||||
self.color = (self.color + 1) % 8
|
||||
|
||||
class SpriteDraw(TokenClient):
|
||||
def InitPersistent(self, owner, client):
|
||||
|
@ -843,10 +868,16 @@ class LobbyBoard(LobbyI):
|
|||
|
||||
def RgObj(self):
|
||||
return self.project.rgdrawing
|
||||
|
||||
def OnObjSelected(self, board):
|
||||
self.client.leaveGame(board)
|
||||
if board.FPlayable():
|
||||
self.owner.SwitchToLobby(LobbyWorld(self.owner, self.client, self.project, board))
|
||||
else:
|
||||
self.client.leaveGame((board, self.game.GameFromDrawing(board)))
|
||||
|
||||
def NewBoard(self, stName):
|
||||
self.OnObjSelected(self.project.NewBoard(stName, self.client.cld.user))
|
||||
|
||||
def NewSprite(self, stName):
|
||||
try:
|
||||
w = int(self.miDimensions.Value("w"))
|
||||
|
@ -855,6 +886,7 @@ class LobbyBoard(LobbyI):
|
|||
self.OnObjSelected(self.project.NewSprite(stName, self.client.cld.user, w, h))
|
||||
except:
|
||||
pass
|
||||
|
||||
def RgstMetadata(self, board):
|
||||
if board != None:
|
||||
return board.RgstMetadata()
|
||||
|
@ -868,17 +900,47 @@ class LobbyProject(LobbyI):
|
|||
miTypein, miBtnNew = self.MiTypein_MiButton("New Project", "ProjName", self.New)
|
||||
return MiMenu([None, None, miTypein, miBtnNew, None, None, None, None, None, None, None, None, MiDgText(self.StMetadata)])
|
||||
|
||||
def StNewObj(self):
|
||||
return "New Project"
|
||||
def RgObj(self):
|
||||
return self.game.rgproject
|
||||
|
||||
def OnObjSelected(self, project):
|
||||
self.owner.SwitchToLobby(LobbyBoard(self.owner, self.client, project))
|
||||
|
||||
def New(self, stName):
|
||||
project = self.game.NewProject(stName, self.client.cld.user)
|
||||
self.OnObjSelected(project)
|
||||
|
||||
def RgstMetadata(self, project):
|
||||
return project.RgstMetadata()
|
||||
|
||||
class LobbyWorld(LobbyI):
|
||||
def InitPersistent(self, owner, client, project, board):
|
||||
self.project = project
|
||||
self.board = board
|
||||
LobbyI.InitPersistent(self, owner, client, None, MiButton("<-- Back to drawings", self.Back), None)
|
||||
|
||||
def CreateMiCmds(self):
|
||||
miBtnNew = MiButton("New Game", self.NewGame)
|
||||
miBtnEdit = MiButton("Edit board", self.Edit)
|
||||
return MiMenu([None, None, miBtnNew, None, miBtnEdit, None, None, None, None, MiDgText(self.StMetadata)])
|
||||
|
||||
def RgObj(self):
|
||||
return self.game.RggameWorld(self.board)
|
||||
|
||||
def OnObjSelected(self, game):
|
||||
self.client.leaveGame((self.board, game))
|
||||
|
||||
def NewGame(self):
|
||||
self.OnObjSelected(self.game.StartNewWorld(self.board))
|
||||
|
||||
def Edit(self):
|
||||
self.client.leaveGame((self.board, self.game.GameFromDrawing(self.board)))
|
||||
|
||||
def Back(self):
|
||||
self.owner.SwitchToLobby(LobbyBoard(self.owner, self.client, self.project, self.board))
|
||||
|
||||
def RgstMetadata(self, game):
|
||||
return [client.cld.user for client in game.RgclientConnected()]
|
||||
|
||||
class RunnerWB(Runner):
|
||||
def InitPersistent(self):
|
||||
|
@ -889,9 +951,9 @@ class RunnerWB(Runner):
|
|||
if (client.joinGame(GameLogin())):
|
||||
client.Cldg(self.gameLobby).drawingSelected = None
|
||||
while True:
|
||||
drawing = client.joinGame(self.gameLobby)
|
||||
drawing, game = client.joinGame(self.gameLobby)
|
||||
client.Cldg(self.gameLobby).drawingSelected = drawing
|
||||
client.joinGame(self.gameLobby.GameFromDrawing(drawing))
|
||||
client.joinGame(game)
|
||||
|
||||
class GameLogin(Game):
|
||||
def GetRgclsTokTrans(self):
|
||||
|
@ -929,6 +991,7 @@ class GameLobby(Game):
|
|||
Game.InitTransient(self)
|
||||
self.mpdrawing_game = Mpsubgame(self, self.MakeGameFromDrawing)
|
||||
self.mpdrawingsynt_game = Mpsubgame(self, self.MakeGameSyntEdit)
|
||||
self.mpboard_rggame = {}
|
||||
|
||||
def GetRgclsTokTrans(self):
|
||||
return [[AutoJoiner, Lobby]]
|
||||
|
@ -955,6 +1018,25 @@ class GameLobby(Game):
|
|||
drawing, synt = drawing_synt
|
||||
return GameSyntEdit(drawing, synt)
|
||||
|
||||
def StartNewWorld(self, board):
|
||||
if board not in self.mpboard_rggame:
|
||||
self.mpboard_rggame[board] = []
|
||||
game = GameWorld(board)
|
||||
game.rgdgdie.append(Partial(self.OnWorldDie, game))
|
||||
self.mpboard_rggame[board].append(game)
|
||||
return game
|
||||
|
||||
def OnWorldDie(self, game):
|
||||
rggame = self.mpboard_rggame[game.board]
|
||||
rggame.remove(game)
|
||||
if len(rggame) == 0:
|
||||
del self.mpboard_rggame[game.board]
|
||||
|
||||
def RggameWorld(self, board):
|
||||
if board in self.mpboard_rggame:
|
||||
return self.mpboard_rggame[board]
|
||||
return []
|
||||
|
||||
def CclientDrawing(self, drawing):
|
||||
if drawing in self.mpdrawing_game:
|
||||
return len(self.mpdrawing_game[drawing].RgclientConnected())
|
||||
|
@ -1039,7 +1121,57 @@ class GameSyntEdit(Game):
|
|||
class GameSprEdit(GameWB):
|
||||
def ClsCursor(self):
|
||||
return CursorSprite
|
||||
|
||||
|
||||
class Player(TokenClient):
|
||||
def InitPersistent(self, owner, client):
|
||||
TokenClient.InitPersistent(self, owner, client, "drawable", "player")
|
||||
self.rbot = self.game.vm.AddPlayer()
|
||||
|
||||
def die(self):
|
||||
self.game.vm.RemovePlayer(self.rbot)
|
||||
TokenClient.die(self)
|
||||
|
||||
def run(self):
|
||||
while True:
|
||||
key = self.EvKey().receive(self)
|
||||
posNew = self.rbot.Pos().Clone()
|
||||
if key == ansi.K_UP:
|
||||
posNew.Up()
|
||||
elif key == ansi.K_DOWN:
|
||||
posNew.Down()
|
||||
elif key == ansi.K_LEFT:
|
||||
posNew.Left()
|
||||
elif key == ansi.K_RIGHT:
|
||||
posNew.Right()
|
||||
if not posNew.Equals(self.rbot.Pos()):
|
||||
# is there an rbot here?
|
||||
rgrbotCollide = [rbot for rbot in self.game.vm.Rgrbot() if rbot != self.rbot and rbot.Pos().Equals(posNew)]
|
||||
if len(rgrbotCollide) > 0:
|
||||
rgrbotCollide[0].botdef.syntOnTouch.Eval(self.game.vm)
|
||||
elif self.game.board.AchAtPos(posNew) == ansi.achBlank:
|
||||
self.rbot.Move(posNew)
|
||||
|
||||
def draw(self, ascr, client):
|
||||
if client == self.client:
|
||||
self.game.board.draw(ascr)
|
||||
for rbot in self.game.vm.Rgrbot():
|
||||
ascr.PutAch(rbot.Ach(), rbot.Pos().X(), rbot.Pos().Y())
|
||||
|
||||
# idea: synchronous event pair to implement "show message" w/ blocking
|
||||
|
||||
class GameWorld(Game):
|
||||
def InitPersistent(self, board):
|
||||
Game.InitPersistent(self)
|
||||
self.board = board
|
||||
self.vm = Vm(board.defs)
|
||||
self.dtStart = datetime.now()
|
||||
|
||||
def StName(self):
|
||||
return self.dtStart.strftime("%b %d, %Y at %I:%M%p") + " [" + str(len(self.RgclientConnected())) + "]"
|
||||
|
||||
def GetRgclsTokTrans(self):
|
||||
return [[AutoJoiner, Player], AutoKiller]
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) > 1:
|
||||
config.override(sys.argv[1])
|
||||
|
|
Loading…
Reference in a new issue