def __init__(self): # layed out in a grid with odd rows a different color for # visual separation #lucky = Grid(9,10, CellPadding=25, CellSpacing=1, BorderWidth=1) lucky = Grid() lucky.resize(9,10) lucky.setBorderWidth(1) lucky.setCellPadding(25) lucky.setCellSpacing(1) val = 0 for x in range(0,9): for y in range(0,10): val += 1 lucky.setText(x,y,val) grid = Grid(1,3,CellPadding=20,CellSpacing=0) rf = grid.getRowFormatter() rf.setStyleName(0, 'oddrow') # popup timer buttons ptb = PopupTimerButton(1) grid.setWidget(0, 0, CaptionPanel('Start the Lucky Number Countdown', ptb, StyleName='left')) grid.setWidget(0, 1, CaptionPanel('Current Lucky Number',ptb.box)) grid.setWidget(0, 2, lucky) # add it all to the root panel RootPanel().add(grid, lucky)
class GridEdit: def onModuleLoad(self): self.input = TextBox() self.input.setEnabled(False) self.input.addKeyboardListener(self) self.g=Grid() self.g.resize(5, 5) self.g.setHTML(0, 0, "<b>Grid Edit</b>") self.g.setBorderWidth(2) self.g.setCellPadding(4) self.g.setCellSpacing(1) self.g.setWidth("500px") self.g.setHeight("120px") self.g.addTableListener(self) self.initGrid() RootPanel().add(self.input) RootPanel().add(self.g) def onKeyDown(self, sender, keycode, modifiers): pass def onKeyUp(self, sender, keycode, modifiers): pass def onKeyPress(self, sender, keycode, modifiers): if keycode == KeyboardListener.KEY_ESCAPE: self.input.setEnabled(False) elif keycode == KeyboardListener.KEY_ENTER: self.input.setEnabled(False) val = self.input.getText() self.set_grid_value(self.row, self.col, val) def onCellClicked(self, sender, row, col): self.row = row self.col = col val = self.values[row][col] self.input.setText(val) self.input.setEnabled(True) self.input.setFocus(True) def set_grid_value(self, row, col, val): self.values[row][col] = val if val == "": val = " " self.g.setHTML(row, col, val) def initGrid(self): self.values = {} for y in range(5): self.values[y] = {} for x in range(5): self.values[y][x] = "" for y in range(5): for x in range(5): val = self.values[y][x] self.set_grid_value(y, x, val)
class GridWidget(AbsolutePanel): def __init__(self): AbsolutePanel.__init__(self) self.page=0 self.min_page=1 self.max_page=10 self.addb=Button("Next >", self) self.subb=Button("< Prev", self) self.clearb=Button("Clear", self) self.g=Grid() self.g.resize(5, 5) self.g.setWidget(0, 0, HTML("<b>Grid Test</b>")) self.g.setBorderWidth(2) self.g.setCellPadding(4) self.g.setCellSpacing(1) self.updatePageDisplay() self.add(self.subb) self.add(self.addb) self.add(self.clearb) self.add(self.g) def onClick(self, sender): if sender == self.clearb: print "clear" self.g.clear() return elif sender==self.addb: self.page+=1 elif sender==self.subb: self.page-=1 self.updatePageDisplay() def updatePageDisplay(self): if self.page<self.min_page: self.page=self.min_page elif self.page>self.max_page: self.page=self.max_page total_pages=(self.max_page-self.min_page) + 1 self.g.setHTML(0, 4, "<b>page %d of %d</b>" % (self.page, total_pages)) if self.page>=self.max_page: self.addb.setEnabled(False) else: self.addb.setEnabled(True) if self.page<=self.min_page: self.subb.setEnabled(False) else: self.subb.setEnabled(True) for y in range(1, 5): for x in range(5): self.g.setText(y, x, "%d (%d,%d)" % (self.page, x, y))
class AccountListSink(VerticalPanel): def __init__(self, hendler = None): VerticalPanel.__init__(self, #HorizontalAlignment=HasAlignment.ALIGN_CENTER, #VerticalAlignment=HasAlignment.ALIGN_MIDDLE, Width="100%", #Height="100%", Spacing=5) self.remote = DataService(['getaccounts']) self.grid = Grid(1, 3, BorderWidth=1, CellPadding=4, CellSpacing=1, StyleName="grid") self.grid.setText(0, 0, u"Number") self.grid.setText(0, 1, u"Type") self.grid.setText(0, 2, u"Balance") formatter = self.grid.getRowFormatter() formatter.setStyleName(0, "grid-header") self.add(Label(u"Accounts")) self.add(self.grid) def updateGrid(self, accounts): rows = len(accounts) if rows > 0: self.grid.resize(rows+1, 3) for row in range(rows): link = PseudoLink(accounts[row]['number'], self.onClick, ID=accounts[row]['number']) self.grid.setWidget(row+1, 0, link) self.grid.setText(row+1, 1, accounts[row]['type']) self.grid.setText(row+1, 2, accounts[row]['balance']) def onShow(self): self.remote.getaccounts(self) def onClick(self, sender): Window.alert(sender.getID()) def onRemoteResponse(self, response, request_info): ''' Called when a response is received from a RPC. ''' if request_info.method == 'getaccounts': #TODO self.updateGrid(response) else: Window.alert('Unrecognized JSONRPC method.') def onRemoteError(self, code, message, request_info): Window.alert(message)
class RightPanel(DockPanel): def __init__(self): DockPanel.__init__(self) self.grids = {} self.g = Grid() self.g.setCellSpacing("0px") self.g.setCellPadding("8px") self.title = HTML(" ") self.title.setStyleName("rightpanel-title") self.add(self.title, DockPanel.NORTH) self.setCellWidth(self.title, "100%") self.setCellHorizontalAlignment(self.title, HasHorizontalAlignment.ALIGN_LEFT) self.add(self.g, DockPanel.CENTER) def setTitle(self, title): self.title.setHTML(title) def clear_items(self): for i in range(len(self.grids)): g = self.grids[i] if hasattr(g, "clear_items"): g.clear_items() self.grids = {} self.g.resize(0, 0) def setup_panels(self, datasets): self.grids = {} self.data = {} self.names = {} self.loaded = {} size = len(datasets) self.g.resize(size, 1) #for i in range(size): # item = datasets[i] # fname = item[0] # self.grids[i] = RightGrid(fname) # self.g.setWidget(i, 0, self.grids[i]) def add_html(self, html, name, index): self.data[index] = html self.names[index] = name self.grids[index] = HTML(html) self.g.setWidget(index, 0, self.grids[index]) def add_items(self, items, name, index): self.data[index] = items self.names[index] = name self.grids[index] = RightGrid("") self.grids[index].set_items(items) self.g.setWidget(index, 0, self.grids[index])
class Underway(HorizontalPanel): def __init__(self): HorizontalPanel.__init__(self, Spacing=4) self.add(Label('Underway:', StyleName='section')) s = ScrollPanel() self.add(s) v = VerticalPanel() s.add(v) self.queued = Grid(StyleName='users') v.add(self.queued) self.button = Button('Refresh', self, StyleName='refresh') self.add(self.button) self.err = Label() self.add(self.err) self.update() def update(self): remote = server.AdminService() id = remote.getUnderway(self) if id < 0: self.err.setText('oops: could not call getUnderway') def onRemoteResponse(self, result, request_info): self.button.setEnabled(True) self.queued.clear() if not result: self.queued.resize(1, 1) self.queued.setText(0, 0, 'No users are currently being added.') else: self.queued.resize(len(result) + 1, 6) self.queued.setText(0, 0, 'Pos') self.queued.setText(0, 1, 'Name') self.queued.setText(0, 2, 'Friends') self.queued.setText(0, 3, '% done') self.queued.setText(0, 4, 'Queued at') self.queued.setText(0, 5, 'Started at') row = 1 for name, nFriends, done, queuedAt, startTime in result: self.queued.setText(row, 0, row) self.queued.setText(row, 1, name) self.queued.setText(row, 2, nFriends) self.queued.setText(row, 3, '%.2f' % done) self.queued.setText(row, 4, queuedAt) self.queued.setText(row, 5, startTime) row += 1 def onRemoteError(self, code, message, request_info): self.button.setEnabled(True) self.err.setText('Could not getUnderway: ' + message) def onClick(self, sender): self.err.setText('') self.button.setEnabled(False) self.update()
class OddGridWidget(DockPanel): def __init__(self, **kwargs): DockPanel.__init__(self, **kwargs) self.grid = Grid(StyleName="datagrid") self.sp = ScrollPanel(self.grid, Width="100%", Height="100%") self.header = Grid(Height="50px") self.add(self.header, DockPanel.NORTH) self.add(self.sp, DockPanel.CENTER) cf = self.setCellHeight(self.header, "50px") cf = self.setCellHeight(self.sp, "100%") self.sortcol = 0 def setData(self, data): self.data = data self.redraw() def sortfn(self, row1, row2): return cmp(row1[self.sortcol], row2[self.sortcol]) def redraw(self): self.data.sort(self.sortfn) rows = len(self.data) cols = 0 if rows > 0: cols = len(self.data[0]) self.grid.resize(rows, cols) self.header.resize(1, cols) cf = self.grid.getCellFormatter() for (nrow, row) in enumerate(self.data): for (ncol, item) in enumerate(row): self.grid.setHTML(nrow, ncol, str(item)) cf.setWidth(nrow, ncol, "200px") cf = self.header.getCellFormatter() self.sortbuttons = [] for ncol in range(cols): sb = Button("sort col %d" % ncol) sb.addClickListener(self) self.header.setWidget(0, ncol, sb) cf.setWidth(0, ncol, "200px") self.sortbuttons.append(sb) def onClick(self, sender): for (ncol, b) in enumerate(self.sortbuttons): if sender == b: self.sortcol = ncol self.redraw()
class Queued(HorizontalPanel): def __init__(self): HorizontalPanel.__init__(self, Spacing=4) self.add(Label("Queued:", StyleName="section")) s = ScrollPanel() self.add(s) v = VerticalPanel() s.add(v) self.queued = Grid(StyleName="users") v.add(self.queued) self.button = Button("Refresh", self, StyleName="refresh") self.add(self.button) self.err = Label() self.add(self.err) self.update() def update(self): remote = server.AdminService() id = remote.getQueued(self) if id < 0: self.err.setText("oops: could not call getQueued") def onRemoteResponse(self, result, request_info): self.button.setEnabled(True) self.queued.clear() if not result: self.queued.resize(1, 1) self.queued.setText(0, 0, "No users are queued for addition.") else: self.queued.resize(len(result) + 1, 4) self.queued.setText(0, 0, "Pos") self.queued.setText(0, 1, "Name") self.queued.setText(0, 2, "Friends") self.queued.setText(0, 3, "Queued at") row = 1 for name, nFriends, time in result: self.queued.setText(row, 0, row) self.queued.setText(row, 1, name) self.queued.setText(row, 2, nFriends) self.queued.setText(row, 3, time) row += 1 def onRemoteError(self, code, message, request_info): self.button.setEnabled(True) self.err.setText("Could not getQueued: " + message) def onClick(self, sender): self.err.setText("") self.button.setEnabled(False) self.update()
def state_to_grid(self, prev_x_board=-1, prev_y_board=-1, prev_x_cell=-1, prev_y_cell=-1): board = self.state.boards for y_board in range(3): for x_board in range(3): # for this mini-grid, do i make buttons or dashes? will_make_buttons = self.will_buttons(y_board, x_board) g = Grid() g.resize(3, 3) g.setBorderWidth(2) g.setCellPadding(9) g.setCellSpacing(1) for y_cell in range(3): for x_cell in range(3): if board[y_board][x_board][y_cell][x_cell][ 'cell'] == 0: if will_make_buttons: b = HTML( '<p style="color:blue">AI %d could<br>play here.</p>' % (self.state.next_piece[2]), self) else: b = HTML('-') elif board[y_board][x_board][y_cell][x_cell][ 'cell'] == 1: if (prev_x_cell == x_cell and prev_y_cell == y_cell and prev_y_board == y_board and prev_x_board == x_board): b = HTML('<p style="color:red">1</p>') else: b = HTML('1') elif board[y_board][x_board][y_cell][x_cell][ 'cell'] == 2: if (prev_x_cell == x_cell and prev_y_cell == y_cell and prev_y_board == y_board and prev_x_board == x_board): b = HTML('<p style="color:red">2</p>') else: b = HTML('2') g.setWidget(y_cell, x_cell, b) self.add(g) self.g.setWidget(y_board, x_board, g)
def onRemoteResponse(self, response, request_info): method = request_info.method if method == 'get_documents': grid = Grid() grid.resize(len(response) + 1, 8) grid.setHTML(0, 0, "Comment") grid.setHTML(0, 1, "Episode") grid.setHTML(0, 2, "When") for (row, item) in enumerate(response): grid.setHTML(row + 1, 0, item.comment) grid.setHTML(row + 1, 1, item.episode) grid.setHTML(row + 1, 2, str(item.clin_when)) #RootPanel().add(grid) self.add(grid) else: self.status.setText(str(response))
def onRemoteResponse(self, response, request_info): method = request_info.method if method == 'get_documents': grid = Grid() grid.resize(len(response)+1, 8) grid.setHTML(0, 0, "Comment") grid.setHTML(0, 1, "Episode") grid.setHTML(0, 2, "When") for (row, item) in enumerate(response): grid.setHTML(row+1, 0, item.comment) grid.setHTML(row+1, 1, item.episode) grid.setHTML(row+1, 2, str(item.clin_when)) #RootPanel().add(grid) self.add(grid) else: self.status.setText(str(response))
def state_to_grid(self, prev_x_board=-1, prev_y_board=-1, prev_x_cell=-1, prev_y_cell=-1): board = self.state.boards for y_board in range(3): for x_board in range(3): # for this mini-grid, do i make buttons or dashes? will_make_buttons = self.will_buttons(y_board, x_board) g=Grid() g.resize(3, 3) g.setBorderWidth(2) g.setCellPadding(9) g.setCellSpacing(1) for y_cell in range(3): for x_cell in range(3): if board[y_board][x_board][y_cell][x_cell]['cell'] == 0: if will_make_buttons: if self.min_player == -1: b = Button('Play 1 here.', self) else: b = Button('Play %d here.' % (self.state.next_piece[2]), self) b.point = {'x_cell':x_cell, 'y_cell':y_cell, 'y_board': y_board, 'x_board': x_board} else: b = HTML('-') elif board[y_board][x_board][y_cell][x_cell]['cell'] == 1: if (prev_x_cell == x_cell and prev_y_cell == y_cell and prev_y_board == y_board and prev_x_board == x_board): b = HTML('<p style="color:red">1</p>') else: b = HTML('1') elif board[y_board][x_board][y_cell][x_cell]['cell'] == 2: if (prev_x_cell == x_cell and prev_y_cell == y_cell and prev_y_board == y_board and prev_x_board == x_board): b = HTML('<p style="color:red">2</p>') else: b = HTML('2') g.setWidget(y_cell, x_cell, b) self.add(g) self.g.setWidget(y_board, x_board, g)
class DynaTableWidget(Composite): def __init__(self, provider, columns, columnStyles, rowCount): Composite.__init__(self) self.acceptor = RowDataAcceptorImpl(self) self.outer = DockPanel() self.startRow = 0 self.grid = Grid() self.navbar = NavBar(self) self.provider = provider self.initWidget(self.outer) self.grid.setStyleName("table") self.outer.add(self.navbar, DockPanel.NORTH) self.outer.add(self.grid, DockPanel.CENTER) self.initTable(columns, columnStyles, rowCount) self.setStyleName("DynaTable-DynaTableWidget") def initTable(self, columns, columnStyles, rowCount): self.grid.resize(rowCount + 1, len(columns)) for i in range(len(columns)): self.grid.setText(0, i, columns[i]) if columnStyles: self.grid.cellFormatter.setStyleName( 0, i, columnStyles[i] + "header") def setStatusText(self, text): self.navbar.status.setText(text) def clearStatusText(self, text): self.navbar.status.setHTML(" ") def refresh(self): self.navbar.gotoFirst.setEnabled(False) self.navbar.gotoPrev.setEnabled(False) self.navbar.gotoNext.setEnabled(False) self.setStatusText("Please wait...") self.provider.updateRowData(self.startRow, self.grid.getRowCount() - 1, self.acceptor) def setRowCount(self, rows): self.grid.resizeRows(rows) def getDataRowCount(self): return self.grid.getRowCount() - 1
class DynaTableWidget(Composite): def __init__(self, provider, columns, columnStyles, rowCount): Composite.__init__(self) self.acceptor = RowDataAcceptorImpl(self) self.outer = DockPanel() self.startRow = 0 self.grid = Grid() self.navbar = NavBar(self) self.provider = provider self.initWidget(self.outer) self.grid.setStyleName("table") self.outer.add(self.navbar, DockPanel.NORTH) self.outer.add(self.grid, DockPanel.CENTER) self.initTable(columns, columnStyles, rowCount) self.setStyleName("DynaTable-DynaTableWidget") def initTable(self, columns, columnStyles, rowCount): self.grid.resize(rowCount + 1, len(columns)) for i in range(len(columns)): self.grid.setText(0, i, columns[i]) if columnStyles: self.grid.cellFormatter.setStyleName(0, i, columnStyles[i] + "header") def setStatusText(self, text): self.navbar.status.setText(text) def clearStatusText(self, text): self.navbar.status.setHTML(" ") def refresh(self): self.navbar.gotoFirst.setEnabled(False) self.navbar.gotoPrev.setEnabled(False) self.navbar.gotoNext.setEnabled(False) self.setStatusText("Please wait...") self.provider.updateRowData(self.startRow, self.grid.getRowCount() - 1, self.acceptor) def setRowCount(self, rows): self.grid.resizeRows(rows) def getDataRowCount(self): return self.grid.getRowCount() - 1
def init(self): '''Initializes the grid on which the game is played. ''' for y_board in range(3): for x_board in range(3): g=Grid() g.resize(3, 3) g.setBorderWidth(2) g.setCellPadding(9) g.setCellSpacing(1) for x_cell in range(3): for y_cell in range(3): b = Button('Play here.', self) b.point = {'x_cell':x_cell, 'y_cell':y_cell, 'y_board': y_board, 'x_board': x_board} g.setWidget(y_cell, x_cell, b) self.add(g) self.g.setWidget(y_board, x_board, g)
class DbTest(): def __init__(self): self.tb = TextBox() self.b = Button("add") self.g = Grid() self.g.resize(4, 2) RootPanel().add(HTML("Add Phrase. Press Button.")) RootPanel().add(self.tb) RootPanel().add(self.b) RootPanel().add(self.g) self.b.addClickListener(self) try: self.db = Factory.createDatabase() self.db.open('database-demo') self.db.execute('create table if not exists Demo' + ' (Phrase varchar(255), Timestamp int)') except: alert( "Could not create database.\nDo you have the google gears extension installed?" ) def onClick(self, sender): phrase = self.tb.getText() currTime = time() self.db.execute('insert into Demo values (?, ?)', phrase, currTime) rs = self.db.execute('select * from Demo order by Timestamp desc') index = 0 while rs.isValidRow(): if index < 4: self.g.setHTML(index, 0, rs.field(0)) self.g.setHTML(index, 1, rs.field(1)) else: self.db.execute('delete from Demo where Timestamp=?', rs.field(1)) index += 1 rs.next() rs.close()
class DbTest(): def __init__(self): self.tb = TextBox() self.b = Button("add") self.g = Grid() self.g.resize(4, 2) RootPanel().add(HTML("Add Phrase. Press Button.")) RootPanel().add(self.tb) RootPanel().add(self.b) RootPanel().add(self.g) self.b.addClickListener(self) try: self.db = Factory.createDatabase() self.db.open('database-demo') self.db.execute('create table if not exists Demo' + ' (Phrase varchar(255), Timestamp int)') except ex: log("could not create database" + str(ex)) def onClick(self, sender): phrase = self.tb.getText() currTime = time() self.db.execute('insert into Demo values (?, ?)', phrase, currTime); rs = self.db.execute('select * from Demo order by Timestamp desc'); index = 0 while rs.isValidRow(): if index <4: self.g.setHTML(index, 0, rs.field(0)) self.g.setHTML(index, 1, rs.field(1)) else: self.db.execute('delete from Demo where Timestamp=?', rs.field(1)); index += 1 rs.next() rs.close()
class Form(FormPanel): def __init__(self, svc, **kwargs): self.describe_listeners = [] if kwargs.has_key('listener'): listener = kwargs.pop('listener') self.addDescribeListener(listener) if kwargs.has_key('data'): data = kwargs.pop('data') else: data = None writebr(repr(data)) FormPanel.__init__(self, **kwargs) self.svc = svc self.grid = Grid() self.grid.resize(0, 3) self.add(self.grid) self.describer = FormDescribeGrid(self) self.saver = FormSaveGrid(self) self.getter = FormGetGrid(self) self.formsetup(data) def addDescribeListener(self, l): self.describe_listeners.append(l) def add_widget(self, description, widget): """ adds a widget, with error rows interspersed """ num_rows = self.grid.getRowCount() self.grid.resize((num_rows + 1), 3) self.grid.setHTML(num_rows, 0, description) self.grid.setWidget(num_rows, 1, widget) def get(self, **kwargs): writebr(repr(kwargs)) self.svc({}, {'get': kwargs}, self.getter) def save(self, data=None): self.clear_errors() if data is None: data = self.getValue() self.data = data writebr(repr(self.data)) self.svc(data, {'save': None}, self.saver) def save_respond(self, response): if not response['success']: errors = response['errors'] self.set_errors(errors) for l in self.describe_listeners: l.onErrors(self, errors) return for l in self.describe_listeners: l.onSaveDone(self, response) def formsetup(self, data=None): if data is None: data = {} self.data = data writebr(repr(self.data)) self.svc(data, {'describe': None}, self.describer) def clear_errors(self): for idx, fname in enumerate(self.fields): self.grid.setHTML(idx, 2, None) def set_errors(self, errors): offsets = {} for idx, fname in enumerate(self.fields): offsets[fname] = idx for k, err in errors.items(): err = "<br />".join(err) idx = offsets[k] self.grid.setHTML(idx, 2, err) def update_values(self, data=None): if data is not None: self.data = data for idx, fname in enumerate(self.fields): val = None if self.data.has_key(fname): val = self.data[fname] w = self.grid.getWidget(idx, 1) w.setValue(val) def do_get(self, response): fields = response.get('instance', None) if fields: self.update_values(fields) for l in self.describe_listeners: l.onRetrieveDone(self, fields) def do_describe(self, fields): self.fields = fields.keys() for idx, fname in enumerate(self.fields): field = fields[fname] if self.data and self.data.has_key(fname): field['initial'] = self.data[fname] writebr("%s %s %d" % (fname, field['label'], idx)) field_type = field['type'] widget_kls = widget_factory.get(field_type, CharField) fv = {} for (k, v) in field.items(): fv[str(k)] = v w = widget_kls(**fv) self.add_widget(field['label'], w) for l in self.describe_listeners: l.onDescribeDone(self) def getValue(self): res = {} for idx, fname in enumerate(self.fields): w = self.grid.getWidget(idx, 1) val = w.getValue() res[fname] = val self.data[fname] = val return res
class GridWidget(AbsolutePanel): def __init__(self): self.state = State() self.game_round = 0 self.TD_CONSTS = {'c3': 1., 'c2': 1., 'c1': 1., 'c6': 1., 'c5': 1., 'c4': 1.} self.CONSTS = {'c3': .5, 'c2': 1., 'c1': 3., 'c6': .5, 'c5': .5, 'c4': .5} self.BEST_CONSTANTS = {'c3': 0.767944, 'c2': 1.049451, 'c1': 3.074038, 'c6': 0.220823, 'c5': 0.281883, 'c4': 0.605861} self.ONES_CONSTS = {'c3': 1., 'c2': 1., 'c1': 1., 'c6': 1., 'c5': 1., 'c4': 1.} AbsolutePanel.__init__(self) self.welcome_label = HTML('<H2 align="center">Welcome to Meta-Tic-Tac-Toe!</H2>To watch the AI play itself, press either "begin game" button. Note: if there is a pop-up saying that the script is taking a long time to complete, this is not a bug - the AI is just taking a while to find the next move. Select the option to continue the script.', StyleName='margins_both') self.add(self.welcome_label) self.depth_limit = 2 self.train_td = Button("Begin game. Learning AI first!", self, StyleName='margins_left') self.add(self.train_td) self.train_static = Button("Begin game. Static AI first!", self, StyleName='margins_left') self.add(self.train_static) self.score_label = Label("CURRENT SCORE: Learning AI: %d | Static AI: %d"% (0,0), StyleName='margins_left') self.add(self.score_label) self.game_over_message = Label("", StyleName='margins_left') self.add(self.game_over_message) StyleSheetCssText(margins) self.increase_depth = Button("Increase ply search depth.", self) self.decrease_depth = Button("Decrease ply search depth.", self) self.depth_label = Label("Current depth is " + str(self.depth_limit) +".") self.depth_grid = Grid(StyleName='margins_left') self.depth_grid.resize(1, 3) self.depth_grid.setBorderWidth(2) self.depth_grid.setCellPadding(9) self.depth_grid.setCellSpacing(1) self.add(self.depth_grid) self.depth_grid.setWidget(0, 0, self.decrease_depth) self.depth_grid.setWidget(0, 1, self.depth_label) self.depth_grid.setWidget(0, 2, self.increase_depth) # initialize the board grid: self.g=Grid(StyleName='margins_left') self.g.resize(3, 3) self.g.setBorderWidth(2) self.g.setCellPadding(9) self.g.setCellSpacing(1) self.init() self.add(self.g) # initialize the contstants adjustment grid: self.adj_grid = Grid(StyleName='margins_left') self.adj_grid.resize(7, 4) self.adj_grid.setBorderWidth(2) self.adj_grid.setCellPadding(9) self.adj_grid.setCellSpacing(1) self.init_constants_adj_grid() self.add(self.adj_grid) self.reset_constants = Button("Reset all of Learning AI's constants to 1.", self, StyleName='margins_left') self.add(self.reset_constants) self.state_to_grid() def init_constants_adj_grid(self): '''Initializes the grid that allows the TD_CONSTS to be adjusted. ''' self.decr_buttons = {} self.adj_learning_labels = {} self.adj_static_labels = {} self.incr_buttons = {} td_keys = ['c1', 'c2', 'c3', 'c4', 'c5', 'c6'] learning_ai_header = Label("Constant for the learning AI.") self.adj_grid.setWidget(0, 0, learning_ai_header) static_ai_header = Label("Constants for the static AI.") self.adj_grid.setWidget(0, 2, static_ai_header) for i, key in enumerate(td_keys): j = i + 1 # off by one because of header... self.adj_learning_labels[key] = Label("Constant %d: %f" % (key[1], self.TD_CONSTS[key])) self.adj_grid.setWidget(j, 0, self.adj_learning_labels[key]) self.decr_buttons[key] = Button('<', self) self.adj_grid.setWidget(j, 1, self.decr_buttons[key]) self.adj_static_labels[key] = Label("Constant %d: %f" % (key[1], self.CONSTS[key])) self.adj_grid.setWidget(j, 2, self.adj_static_labels[key]) self.incr_buttons[key] = Button('>', self) self.adj_grid.setWidget(j, 3, self.incr_buttons[key]) def init(self): '''Initializes the grid on which the game is played. ''' for y_board in range(3): for x_board in range(3): g=Grid() g.resize(3, 3) g.setBorderWidth(2) g.setCellPadding(9) g.setCellSpacing(1) for x_cell in range(3): for y_cell in range(3): b = Button('AI could play here.', self) b.point = {'x_cell':x_cell, 'y_cell':y_cell, 'y_board': y_board, 'x_board': x_board} g.setWidget(y_cell, x_cell, b) self.add(g) self.g.setWidget(y_board, x_board, g) def start_new_game(self): #g.__init__() nope, can't use this :( g.state = State() g.game_over = False self.depthLimit = 2 self.human_first = True self.check_is_win() self.max_player = '-1' self.min_player = '-1' self.state_to_grid() def onClick(self, sender): self.check_adjusts(sender) if sender == self.reset_constants: self.TD_CONSTS = self.ONES_CONSTS self.sync_consts() if sender == self.increase_depth: self.depth_limit += 1 self.depth_label.setText("Current depth is " + str(self.depth_limit) +".") if sender == self.decrease_depth: self.depth_limit -= 1 self.depth_label.setText("Current depth is " + str(self.depth_limit) +".") if sender == self.train_td: self.state = State() self.static_ai_str = '2' self.td_ai_str = '1' self.state.next_piece = [1, 1, 1] Timer(250, notify=self.td_ai_turn) if sender == self.train_static: self.state = State() self.static_ai_str = '1' self.td_ai_str = '2' self.state.next_piece = [1, 1, 1] Timer(250, notify=self.static_ai_turn) def check_adjusts(self, sender): td_keys = ['c1', 'c2', 'c3', 'c4', 'c5', 'c6'] for key in td_keys: if self.incr_buttons[key] == sender: self.change_td_const(key, '+') if self.decr_buttons[key] == sender: self.change_td_const(key, '-') self.TD_CONSTS = normalize(self.TD_CONSTS) self.adj_learning_labels[key].setText("Constant %d: %f" % (key[1], self.TD_CONSTS[key])) self.sync_consts() def change_td_const(self, key, sign): if sign == '+': self.CONSTS[key] += INCREMENT_AMOUNT elif sign == '-': self.CONSTS[key] -= INCREMENT_AMOUNT def sync_consts(self): """Sync td rates with the current state. """ td_keys = ['c1', 'c2', 'c3', 'c4', 'c5', 'c6'] for key in td_keys: self.adj_learning_labels[key].setText("Constant %d: %f" % (key[1], self.TD_CONSTS[key])) self.adj_static_labels[key].setText("Constant %d: %f" % (key[1], self.CONSTS[key])) def check_is_win(self, last_position={}): self.state_to_grid(prev_x_board=last_position['x_board'], prev_y_board=last_position['y_board'], prev_x_cell=last_position['x_cell'], prev_y_cell=last_position['y_cell'],) learning_ai_score = self.state.score[self.td_ai_str] static_ai_score = self.state.score[self.static_ai_str] self.score_label.setText("CURRENT SCORE: Learning AI(%d): %d | Static AI(%d): %d" % (self.td_ai_str, learning_ai_score, self.static_ai_str, static_ai_score)) self.state.printInfo() if is_over(self.state): if learning_ai_score > static_ai_score: msg = "the learning AI won with score %d vs %d." % (learning_ai_score, static_ai_score) elif learning_ai_score < static_ai_score: msg = "the static AI won with score %d vs %d." % (static_ai_score, learning_ai_score) elif learning_ai_score == static_ai_score: msg = "the game ended in a tie." self.game_round += 1 game_over_message.setText("In game round " + str(self.game_round) + ", " + msg) return True else: return False def static_ai_turn(self): print "\n\nNaive AIs turn which plays the piece: ", self.state.next_piece[2] print "next piece is ", self.state.next_piece print "TD_CONSTS", self.TD_CONSTS (expectedUtility, next_state) = ab(self.state, self.CONSTS, depth_limit=self.depth_limit) last_position = find_last_move(self.state, next_state) self.state = next_state self.state.printInfo() over = self.check_is_win(last_position) print "back in static" if not over: self.pause_update = Timer(250, notify=self.td_ai_turn) else: return True def td_ai_turn(self): print "\n\nTD AI player starting turn. TD AI places the piece:", self.state.next_piece[2] print "TD_CONSTS after being adjusted are: ", self.TD_CONSTS # print, alpha-beta search etc.: (expectedUtility, state) = ab(self.state, self.TD_CONSTS, depth_limit=self.depth_limit) terminal_state = expectedUtility.terminal self.TD_CONSTS = td_learning(terminal_state, self.TD_CONSTS, self.state) self.sync_consts() # reflect the new TD_CONSTS in the game. last_position = find_last_move(self.state, state) self.state = state state.printInfo() print "TD_CONSTS after being adjusted are: ", self.TD_CONSTS over = self.check_is_win(last_position) print "back in td" print "Is over ", over if not over: return Timer(250, notify=self.static_ai_turn) else: return True def will_buttons(self, y_board, x_board): # first we determine if the next_piece points to a playable board. board = self.state.boards piece = list(self.state.next_piece) playable = True if is_win(board[piece[0]][piece[1]]) or is_full(board[piece[0]][piece[1]]): playable = False if (not is_win(board[y_board][x_board])) and (not is_full(board[y_board][x_board])): if not playable: return True if playable: return (y_board == piece[0]) and (x_board == piece[1]) return False def state_to_grid(self, prev_x_board=-1, prev_y_board=-1, prev_x_cell=-1, prev_y_cell=-1): board = self.state.boards for y_board in range(3): for x_board in range(3): # for this mini-grid, do i make buttons or dashes? will_make_buttons = self.will_buttons(y_board, x_board) g=Grid() g.resize(3, 3) g.setBorderWidth(2) g.setCellPadding(9) g.setCellSpacing(1) for y_cell in range(3): for x_cell in range(3): if board[y_board][x_board][y_cell][x_cell]['cell'] == 0: if will_make_buttons: b = HTML('<p style="color:blue">AI %d could<br>play here.</p>' % (self.state.next_piece[2]), self) else: b = HTML('-') elif board[y_board][x_board][y_cell][x_cell]['cell'] == 1: if (prev_x_cell == x_cell and prev_y_cell == y_cell and prev_y_board == y_board and prev_x_board == x_board): b = HTML('<p style="color:red">1</p>') else: b = HTML('1') elif board[y_board][x_board][y_cell][x_cell]['cell'] == 2: if (prev_x_cell == x_cell and prev_y_cell == y_cell and prev_y_board == y_board and prev_x_board == x_board): b = HTML('<p style="color:red">2</p>') else: b = HTML('2') g.setWidget(y_cell, x_cell, b) self.add(g) self.g.setWidget(y_board, x_board, g)
class Form(FormPanel): def __init__(self, svc, **kwargs): self.describe_listeners = [] if kwargs.has_key('listener'): listener = kwargs.pop('listener') self.addDescribeListener(listener) if kwargs.has_key('data'): data = kwargs.pop('data') else: data = None FormPanel.__init__(self, **kwargs) self.svc = svc self.grid = Grid() self.grid.resize(0, 3) self.add(self.grid) self.describer = FormDescribeGrid(self) self.saver = FormSaveGrid(self) self.getter = FormGetGrid(self) self.formsetup(data) def addDescribeListener(self, l): self.describe_listeners.append(l) def add_widget(self, description, widget): """ adds a widget, with error rows interspersed """ num_rows = self.grid.getRowCount() self.grid.resize((num_rows+1), 3) self.grid.setHTML(num_rows, 0, description) self.grid.setWidget(num_rows, 1, widget) def get(self, **kwargs): writebr(repr(kwargs)) self.svc({}, {'get': kwargs}, self.getter) def save(self, data=None): self.clear_errors() if data is None: data = self.getValue() self.data = data writebr(repr(self.data)) self.svc(data, {'save': None}, self.saver) def save_respond(self, response): if not response['success']: errors = response['errors'] self.set_errors(errors) for l in self.describe_listeners: l.onErrors(self, errors) return for l in self.describe_listeners: l.onSaveDone(self, response) def formsetup(self, data=None): if data is None: data = {} self.data = data self.svc(data, {'describe': None}, self.describer) def clear_errors(self): for idx, fname in enumerate(self.fields): self.grid.setHTML(idx, 2, None) def set_errors(self, errors): offsets = {} for idx, fname in enumerate(self.fields): offsets[fname] = idx for k, err in errors.items(): err = "<br />".join(err) idx = offsets[k] self.grid.setHTML(idx, 2, err) def update_values(self, data = None): if data is not None: self.data = data for idx, fname in enumerate(self.fields): val = None if self.data.has_key(fname): val = self.data[fname] w = self.grid.getWidget(idx, 1) w.setValue(val) def do_get(self, response): fields = response.get('instance', None) if fields: self.update_values(fields) for l in self.describe_listeners: l.onRetrieveDone(self, fields) def do_describe(self, fields): self.fields = fields.keys() for idx, fname in enumerate(self.fields): field = fields[fname] if self.data and self.data.has_key(fname): field['initial'] = self.data[fname] field_type = field['type'] widget_kls = widget_factory.get(field_type, CharField) fv = {} for (k, v) in field.items(): fv[str(k)] = v w = widget_kls(**fv) self.add_widget(field['label'], w) for l in self.describe_listeners: l.onDescribeDone(self) def getValue(self): res = {} for idx, fname in enumerate(self.fields): w = self.grid.getWidget(idx, 1) val = w.getValue() res[fname] = val self.data[fname] = val return res
class GridWidget(AbsolutePanel): def __init__(self): AbsolutePanel.__init__(self) StyleSheetCssText(margins) # initialize css... header = """<div><H2 align="center">Welcome to Unbeatable Tic-Tac-Toe!</H2><br>My <a href="https://github.com/chetweger/min-max-games/blob/master/ttt/ttt.py">implementation</a> uses the min-max search algorithm with alpha beta pruning and a transposition table!</div>""" header = HTML(header, StyleName='margins_both') self.add(header) self.ai_first = Button("AI first.", self, StyleName='margins_left') self.add(self.ai_first) self.new_game = Button("New game", self, StyleName='margins_left') self.add(self.new_game) self.g=Grid(StyleName='margins_left') self.g.resize(3, 3) self.g.setBorderWidth(2) self.g.setCellPadding(4) self.g.setCellSpacing(1) self.init() self.add(self.g) self.state = State() self.game_resolution=Label("", StyleName='margins_left') self.add(self.game_resolution) def start_new_game(self): self.state = State() self.game_over = False self.ai_first.setVisible(True) self.state_to_grid(self.state) def onClick(self, sender): if sender == self.ai_first: print 'player is ', self.state.player self.state.max_v = 1 self.state.min_v = 2 self.ai_first.setVisible(False) print 'button ai_first exists', hasattr(self, 'ai_first') self.state.print_me() next_state = ab(self.state) self.state = next_state self.state_to_grid(next_state) print '[after]player is ', self.state.player elif sender == self.new_game: self.start_new_game() else: print 'player is ', self.state.player ''' self.g.setText(0, 1, 'wassup') self.g.setText(p['x'], p['y'], str(self.state.min_v)) ''' if self.ai_first.isVisible(): print 'Setting state.max_v' self.state.max_v = 2 self.state.min_v = 1 self.ai_first.setVisible(False) p = sender.point self.g.setText(p['y'], p['x'], str(self.state.player)) self.state = self.grid_to_state() self.check_for_tie() # end 1 if is_win(self.state): self.state_to_grid(self.state, game_over=True, over_message='You won! This should not happen. This is a bug. Please email [email protected] describing the conditions of the game.') self.state.player = next_player(self.state.player) self.state.print_me() next_state = ab(self.state) self.state = next_state self.state_to_grid(next_state) self.check_for_tie() # end 1 if is_win(self.state): self.state_to_grid(self.state, game_over=True, over_message='You lost! Better luck next time.') def check_for_tie(self): if is_over(self.state): self.state_to_grid(self.state, game_over=True, over_message='The game is a tie.') def state_to_grid(self, state, game_over=False, over_message=''): if over_message: self.game_resolution.setText(over_message) self.game_resolution.setVisible(True) else: self.game_resolution.setVisible(False) board = state.board for y in range(3): for x in range(3): if board[y][x] == 0: if not game_over: b = Button('Press', self) b.point = {'x':x, 'y':y} self.g.setWidget(y, x, b) else: self.g.setText(y, x, '-') elif board[y][x] == '1': self.g.setText(y, x, '1') elif board[y][x] == '2': self.g.setText(y, x, '2') else: print 'state_to_grid exception' #assert False def grid_to_state(self): next_state = State() for y in range(3): for x in range(3): if isinstance(self.g.getWidget(y, x), Button): print y, x next_state.board[y][x] = 0 elif self.g.getText(y, x) == '1' or self.g.getText(y, x) == '2': next_state.board[y][x] = int(self.g.getText(y,x)) else: print 'grid_to_state exception' #assert False next_state.min_v = self.state.min_v next_state.max_v = self.state.max_v next_state.player = self.state.player return next_state def init(self): for y in range(3): for x in range(3): b = Button('Press', self) b.point = {'x':x, 'y':y} self.g.setWidget(y, x, b)
class Viewer: def __init__(self, db_url, parent_panel, doc_callback=None, page_size=5): self.db_url = db_url self.parent_panel = parent_panel self.doc_callback = doc_callback self.page_size = page_size def onModuleLoad(self): ## Grid setup self.grid = Grid() # Note: The resize method args are Rows,Cols (Curses style) self.grid.resize(1,4) self.grid.setBorderWidth(1) self.grid.setHTML(0,0,'#') self.grid.setHTML(0,1,'ID') self.grid.setHTML(0,2,'Revision') self.grid.setHTML(0,3,'Delete') self.grid.addTableListener(self) self.parent_panel.add(self.grid) ## Buttons self.button_panel = HorizontalPanel() # Prev self.first_button = Button("<-", self.firstPage) self.first_button.setEnabled(False) self.button_panel.add(self.first_button) self.prev_button = Button("Previous", self.prevPage) self.prev_button.setEnabled(False) self.button_panel.add(self.prev_button) self.next_button = Button("Next", self.nextPage) self.next_button.setEnabled(False) self.button_panel.add(self.next_button) self.parent_panel.add(self.button_panel) def populate(self, json): view_obj = JSONParser().decode(json) view_rows = view_obj['rows'] offset = view_obj['offset'] num_rows = len(view_rows) self.first_key = view_rows[0]['key'] if offset != 0: self.first_button.setEnabled(True) if num_rows > self.page_size: self.next_key = view_rows[-1:][0]['key'] self.next_button.setEnabled(True) self.grid.resize(self.page_size+1,4) else: self.grid.resize(num_rows+1,4) for row_num in range(num_rows): if row_num < self.page_size: self.grid.setHTML(row_num+1, 0, 1+offset+row_num) self.grid.setHTML(row_num+1, 1, view_rows[row_num]['key']) self.grid.setHTML(row_num+1, 2, view_rows[row_num]['value']['rev']) self.grid.setHTML(row_num+1, 3, '<b>X O X</b>') if len(self.prev_keys)>0: self.prev_button.setEnabled(True) def onCellClicked(self, sender, row, col): doc_id = self.grid.getHTML(row, 1) if col == 3: doc_rev = self.grid.getHTML(row, 2) url = self.db_url+doc_id+'?rev='+doc_rev HTTPRequest().asyncDelete(None, None, url=url, handler=DeleteHandler(self)) else: if self.doc_callback is not None: self.doc_callback(doc_id) def firstPage(self): self.loadPage(None) def nextPage(self): self.prev_keys.append(self.first_key) self.loadPage(self.next_key) def prevPage(self): self.loadPage(self.prev_keys.pop()) def setView(self, view_path, first_key = None): self.view_path = view_path #self.prev_keys = [] #self.next_key = None self.loadPage(first_key) def loadPage(self, startkey=None): limit = int(self.page_size)+1 view_url = self.db_url+self.view_path+'?limit=%d'%limit if startkey is not None: view_url += '&startkey="%s"'%startkey else: self.prev_keys = [] self.first_button.setEnabled(False) self.next_button.setEnabled(False) self.prev_button.setEnabled(False) HTTPRequest().asyncGet(None, None, url=view_url, handler=ViewLoader(self))
class InputBox(FocusPanel): _props = [ ("maxLength", "Max Length", "MaxLength", int), ("text", "Text", "Text", None), ("matchPattern", "Match Pattern", "MatchPattern", None), ("cursorStyle", "Cursor Style", "CursorStyle", None), ] @classmethod def _getProps(self): return FocusPanel._getProps() + self._props def __init__(self, **kwargs): """ setMatchPattern - defaults to '' to match everything match pattern examples: '^[0-9]*$' is for digits only '^[0-9,A-Z]*$' is for digits and uppercase setMaxLength setText OB """ kwargs['MatchPattern'] = kwargs.pop('MatchPattern', '') cs = kwargs.pop('CursorStyle', "inputbox-cursor") gs = kwargs.pop('StyleName', 'gwt-inputbox') ap = AbsolutePanel(StyleName="inputbox") self.tp = Grid(StyleName=gs, Width="100%", Height="100%", CellPadding=0, CellSpacing=0) self.cursor = HTML(StyleName=cs) ap.add(self.tp) ap.add(self.cursor, 0, 0) self.cf = self.tp.getCellFormatter() FocusPanel.__init__(self, Widget=ap, **kwargs) self.addTableListener(self) self.addKeyboardListener(self) self.addFocusListener(self) self.word_selected_pos = 0 self.ctimer = Timer(notify=self.cursorFlash) self.focusset = False self.cstate = False self._keypressListeners = [] def addKeypressListener(self, listener): self._keypressListeners.append(listener) def removeKeypressListener(self, listener): self._keypressListeners.remove(listener) def getMatchPattern(self): return self.mp def setMatchPattern(self, mp): self.mp = mp self.rexp = re.compile(self.mp) def addDblTableListener(self, listener): self.tp.addDblTableListener(listener) def addTableListener(self, listener): self.tp.addTableListener(listener) def _move_cursor(self, col): """ moves the css-styled cursor """ #old style (useful for insert mode - don't delete this line for now!) #self.cf.setStyleName(0, col, "inputbox-square-word-cursor", highlight) el = self.cf.getRawElement(0, col+1) w = self.getWidget() px = self.tp.getAbsoluteLeft() py = self.tp.getAbsoluteTop() width = DOM.getOffsetWidth(el) px = DOM.getAbsoluteLeft(el) - px py = DOM.getAbsoluteTop(el) - py w.setWidgetPosition(self.cursor, px, py) def _highlight_cursor(self, col, highlight): """ highlights (or dehighlights) the currently selected cell """ #old style (useful for insert mode - don't delete this line for now!) #self.cf.setStyleName(0, col, "inputbox-square-word-cursor", highlight) print "_highlight", col, highlight self._move_cursor(col) self.cursor.setStyleName("inputbox-square-word-cursor", highlight) def set_grid_value(self, v, y, x): if v: w = "" else: w = "0px" v = v or EMPTY s = HTML(v, StyleName="inputbox-square") self.tp.setWidget(y, x, s) self.cf.setAlignment(y, x, HasAlignment.ALIGN_LEFT, HasAlignment.ALIGN_MIDDLE) self.cf.setWidth(y, x, w) s.setWidth(w) def onKeyDown(self, sender, keycode, modifiers): evt = DOM.eventGetCurrentEvent() DOM.eventPreventDefault(evt) if self.word_selected_pos is None: return val = chr(keycode) done = False if keycode == KeyboardListener.KEY_DELETE: self.shift_letters_back() done = True elif keycode == KeyboardListener.KEY_BACKSPACE: if not self.nasty_hack(): if self.moveCursor(-1): self.shift_letters_back() done = True elif keycode == KeyboardListener.KEY_LEFT: self.moveCursor(-1) done = True elif keycode == KeyboardListener.KEY_RIGHT: self.moveCursor(1) done = True print "onKeyDown", keycode, val, self.rexp.match(val) if not done: if self.rexp.match(val): self.press_letter(val) for listener in self._keypressListeners: listener.onKeyPressed(sender, keycode, modifiers) def press_letter(self, val): print "press letter", val # check the key is a letter, and there's a grid position highlighted if self.word_selected_pos is None: return row = 0 col = self.word_selected_pos self.highlight_cursor(False) self.set_grid_value(val, row, col) self.moveCursor(1) def nasty_hack(self): """ breaking of backspace/delete rules for the final character """ row = 0 col = self.word_selected_pos txt = self.get_char(col) if txt is None or txt == EMPTY: return False self.set_grid_value(EMPTY, row, col) return True def shift_letters_back(self): """ this function is used by del and backspace, to move the letters backwards from after the cursor. the only difference between backspace and delete is that backspace moves the cursor and _then_ does letter-moving. """ self.highlight_cursor(False) row = 0 col = self.word_selected_pos x2 = self.tp.getColumnCount()-2 while (x2 != col): txt = self.get_char(col+1) self.set_grid_value(txt, row, col) col += 1 self.set_grid_value(EMPTY, row, col) def setCursorPos(self, col): x2 = self.tp.getColumnCount()-1 col = min(x2, col) col = max(col, 0) if self.get_char(0) is None or self.get_char(0) == EMPTY: col = 0 while (self.get_char(col-1) is None or \ self.get_char(col-1) == EMPTY) and col > 1: col -= 1 self._move_cursor(col) self.highlight_cursor(False) self.word_selected_pos = col self.highlight_cursor(self.focusset) return True def getCursorPos(self): return self.word_selected_pos def moveCursor(self, dirn): x2 = self.tp.getColumnCount()-1 row = 0 col = self.word_selected_pos if dirn == 1 and x2 == col+1: return False if dirn == -1 and 0 == col+1: return False return self.setCursorPos(col+dirn) def onKeyUp(self, sender, keycode, modifiers): evt = DOM.eventGetCurrentEvent() DOM.eventCancelBubble(evt, True) DOM.eventPreventDefault(evt) def onKeyPress(self, sender, keycode, modifiers): evt = DOM.eventGetCurrentEvent() DOM.eventPreventDefault(evt) def highlight_cursor(self, highlight): """ highlights (or dehighlights) the currently selected cell """ if self.word_selected_pos is None: return col = self.word_selected_pos self._highlight_cursor(col, highlight) def getMaxLength(self): return self.tp.getColumnCount()-1 def setMaxLength(self, x): l = max(0, self.tp.getColumnCount()-1) self.tp.resize(1, x+1) self.clear(l) def clear(self, fromrange=0): for i in range(fromrange, self.tp.getColumnCount()): self.set_grid_value(EMPTY, 0, i) self.cf.setWidth(0, self.tp.getColumnCount()-1, "100%") def onCellClicked(self, listener, row, col, direction=None): self.setCursorPos(col) def cursorFlash(self, timr): if not self.focusset: return self.highlight_cursor(self.cstate) self.cstate = not self.cstate def onFocus(self, sender): print "onFocus", sender self.focusset = True self.ctimer.scheduleRepeating(800) def onLostFocus(self, sender): print "onLostFocus", sender self.focusset = False self.ctimer.cancel() self.highlight_cursor(False) def get_char(self, x): w = self.tp.getWidget(0, x) return w and w.getHTML() def getText(self): txt = '' for i in range(self.tp.getColumnCount()-1): c = self.get_char(i) if c is None or c == EMPTY: break txt += c return txt def setText(self, txt): self.highlight_cursor(False) self.clear() txt = txt[:self.getMaxLength()] for (i, c) in enumerate(txt): self.set_grid_value(c, 0, i) self.setCursorPos(min(self.getMaxLength()-1, len(txt)))
class GridWidget(AbsolutePanel): def __init__(self): self.state = State() self.game_over = False self.TD_CONSTS = {'c3': 0.767944, 'c2': 1.049451, 'c1': 3.074038, 'c6': 0.220823, 'c5': 0.281883, 'c4': 0.605861} AbsolutePanel.__init__(self) StyleSheetCssText(margins) # initialize css... self.welcome_label = HTML('<H2 align="center">Welcome to Meta-Tic-Tac-Toe!</H2><p>Play first by clicking on one of the positions in the middle board or let the AI go first by clicking on "AI first". To change the difficulty click on "Increase/Decrease search depth". Note: if there is a pop-up saying that the script is taking a long time to complete, this is not a bug - the AI is just taking a while to find the next move. Select the option to continue the script.</p>', StyleName='margins_both') self.add(self.welcome_label) self.depthLimit = 3 self.human_first = True self.ai_first = Button("AI first.", self, StyleName='margins_left') self.add(self.ai_first) self.increase_depth = Button("Increase search depth", self) self.decrease_depth = Button("Decrease search depth", self) self.depth_label = HTML("""AI will search to a <a href="#depth_explanation">depth</a> of """ + str(self.depthLimit) +".") self.depth_grid = Grid(StyleName='margins_left') self.depth_grid.resize(1, 3) self.depth_grid.setBorderWidth(2) self.depth_grid.setCellPadding(9) self.depth_grid.setCellSpacing(1) self.add(self.depth_grid) self.depth_grid.setWidget(0, 0, self.decrease_depth) self.depth_grid.setWidget(0, 1, self.depth_label) self.depth_grid.setWidget(0, 2, self.increase_depth) self.new_game = Button("New game", self, StyleName='margins_left') self.add(self.new_game) self.score_label = Label("CURRENT SCORE: Human: %d | AI: %d"% (0,0), StyleName='margins_left') self.add(self.score_label) self.game_over_msg = HTML("", StyleName='margins_left') self.add(self.game_over_msg) # initialize the board grid: self.g=Grid(StyleName='margins_left') self.g.resize(3, 3) self.g.setBorderWidth(2) self.g.setCellPadding(9) self.g.setCellSpacing(1) self.init() self.add(self.g) # initialize the contstants adjustment grid: self.adj_grid = Grid(StyleName='margins_left') self.adj_grid.resize(7, 3) self.adj_grid.setBorderWidth(2) self.adj_grid.setCellPadding(9) self.adj_grid.setCellSpacing(1) self.init_constants_adj_grid() self.add(self.adj_grid) self.max_player = '-1' self.min_player = '-1' self.state_to_grid() def init_constants_adj_grid(self): '''Initializes the grid that allows the TD_CONSTS to be adjusted. ''' self.decr_buttons = {} self.adj_labels = {} self.incr_buttons = {} td_keys = ['c1', 'c2', 'c3', 'c4', 'c5', 'c6'] self.adj_grid.setWidget(0, 1, HTML('''Adjust the <a href="#utility_function">constants</a> to change<br>the AI's behavior.''')) for i, key in enumerate(td_keys): j = i + 1 self.decr_buttons[key] = Button('<', self) self.adj_grid.setWidget(j, 0, self.decr_buttons[key]) self.incr_buttons[key] = Button('>', self) self.adj_grid.setWidget(j, 2, self.incr_buttons[key]) self.adj_labels[key] = Label("Constant %d: %f" % (key[1], self.TD_CONSTS[key])) self.adj_grid.setWidget(j, 1, self.adj_labels[key]) def init(self): '''Initializes the grid on which the game is played. ''' for y_board in range(3): for x_board in range(3): g=Grid() g.resize(3, 3) g.setBorderWidth(2) g.setCellPadding(9) g.setCellSpacing(1) for x_cell in range(3): for y_cell in range(3): b = Button('Play here.', self) b.point = {'x_cell':x_cell, 'y_cell':y_cell, 'y_board': y_board, 'x_board': x_board} g.setWidget(y_cell, x_cell, b) self.add(g) self.g.setWidget(y_board, x_board, g) def start_new_game(self): #g.__init__() nope, can't use this :( self.state = State() self.game_over = False self.depthLimit = 3 self.human_first = True self.ai_first.setVisible(True) # new game, so we make this button visible self.check_win() self.max_player = '-1' self.min_player = '-1' self.state_to_grid() def onClick(self, sender): if sender == self.increase_depth: self.depthLimit += 1 self.depth_label.setHTML("""AI will search to a <a href="#depth_explanation">depth</a> of """ + str(self.depthLimit) +".") if sender == self.decrease_depth: self.depthLimit -= 1 self.depth_label.setHTML("""AI will search to a <a href="#depth_explanation">depth</a> of """ + str(self.depthLimit) +".") if sender == self.new_game: self.start_new_game() self.check_adjusts(sender) if not self.game_over: if sender == self.ai_first and self.min_player == -1: # we only set min_player and max_player when they are not yet initialized self.human_first = False self.max_player = '1' self.min_player = '2' self.state.next_piece[2] = self.max_player self.ai_first.setVisible(False) # can't go first any more so we make it invisible... new_state = ab(self.state, self.TD_CONSTS, depth_limit=self.depthLimit)[1] last_position = find_last_move(self.state, new_state) self.state = new_state self.state_to_grid(prev_x_board=last_position['x_board'], prev_y_board=last_position['y_board'], prev_x_cell=last_position['x_cell'], prev_y_cell=last_position['y_cell'],) if hasattr(sender, 'point'): if self.min_player == -1: # we only set min_player and max_player when they are not yet initialized self.max_player = '2' self.min_player = '1' self.ai_first.setVisible(False) # can't go first any more so we make it invisible... point = sender.point g = self.g.getWidget(point['y_board'], point['x_board']) g.setText(point['y_cell'], point['x_cell'], str(self.min_player)) self.grid_to_state(point) self.check_win() self.state.next_piece[2] = self.max_player new_state = ab(self.state, self.TD_CONSTS, depth_limit=self.depthLimit)[1] last_position = find_last_move(self.state, new_state) self.state = new_state self.state_to_grid(prev_x_board=last_position['x_board'], prev_y_board=last_position['y_board'], prev_x_cell=last_position['x_cell'], prev_y_cell=last_position['y_cell'],) self.check_win() def check_adjusts(self, sender): td_keys = ['c1', 'c2', 'c3', 'c4', 'c5', 'c6'] for key in td_keys: if self.incr_buttons[key] == sender: self.change_td_const(key, '+') if self.decr_buttons[key] == sender: self.change_td_const(key, '-') self.adj_labels[key].setText("Constant %d: %f" % (key[1], self.TD_CONSTS[key])) def change_td_const(self, key, sign): if sign == '+': self.TD_CONSTS[key] += INCREMENT_AMOUNT elif sign == '-': self.TD_CONSTS[key] -= INCREMENT_AMOUNT def check_win(self): self.depth_label.setHTML("""AI will search to a <a href="#depth_explanation">depth</a> of """ + str(self.depthLimit) +".") self.check_adjusts(None) human_score = self.state.score[str(self.min_player)] ai_score = self.state.score[str(self.max_player)] self.score_label.setText("CURRENT SCORE: Human(%d): %d | AI(%d): %d" % (self.min_player, human_score, self.max_player, ai_score)) if is_over(self.state): if human_score > ai_score: msg = "Congratulations, you won! To increase the difficulty, increase the search depth." elif human_score < ai_score: msg = "You lost! Better luck next time." elif human_score == ai_score: msg = "Game ends in a tie." self.game_over_msg.setHTML("<H3>" + msg + "</H3>") self.game_over = True if self.game_over: self.game_over_msg.setVisible(True) else: self.game_over_msg.setVisible(False) def will_buttons(self, y_board, x_board): # first we determine if the next_piece points to a playable board. board = self.state.boards piece = list(self.state.next_piece) playable = True if is_win(board[piece[0]][piece[1]]) or is_full(board[piece[0]][piece[1]]): playable = False if (not is_win(board[y_board][x_board])) and (not is_full(board[y_board][x_board])): if not playable: return True if playable: return (y_board == piece[0]) and (x_board == piece[1]) return False def state_to_grid(self, prev_x_board=-1, prev_y_board=-1, prev_x_cell=-1, prev_y_cell=-1): board = self.state.boards for y_board in range(3): for x_board in range(3): # for this mini-grid, do i make buttons or dashes? will_make_buttons = self.will_buttons(y_board, x_board) g=Grid() g.resize(3, 3) g.setBorderWidth(2) g.setCellPadding(9) g.setCellSpacing(1) for y_cell in range(3): for x_cell in range(3): if board[y_board][x_board][y_cell][x_cell]['cell'] == 0: if will_make_buttons: if self.min_player == -1: b = Button('Play 1 here.', self) else: b = Button('Play %d here.' % (self.state.next_piece[2]), self) b.point = {'x_cell':x_cell, 'y_cell':y_cell, 'y_board': y_board, 'x_board': x_board} else: b = HTML('-') elif board[y_board][x_board][y_cell][x_cell]['cell'] == 1: if (prev_x_cell == x_cell and prev_y_cell == y_cell and prev_y_board == y_board and prev_x_board == x_board): b = HTML('<p style="color:red">1</p>') else: b = HTML('1') elif board[y_board][x_board][y_cell][x_cell]['cell'] == 2: if (prev_x_cell == x_cell and prev_y_cell == y_cell and prev_y_board == y_board and prev_x_board == x_board): b = HTML('<p style="color:red">2</p>') else: b = HTML('2') g.setWidget(y_cell, x_cell, b) self.add(g) self.g.setWidget(y_board, x_board, g) def grid_to_state(self, point): board = self.state.boards for y_board in range(3): for x_board in range(3): g = self.g.getWidget(y_board, x_board) for y_cell in range(3): for x_cell in range(3): if isinstance(g.getWidget(y_cell, x_cell), Button): assert board[y_board][x_board][y_cell][x_cell]['cell'] == 0 elif (g.getText(y_cell, x_cell) == '1') or (g.getText(y_cell, x_cell) == '2'): if self.state.boards[y_board][x_board][y_cell][x_cell]['cell'] == 0: self.state.boards[y_board][x_board][y_cell][x_cell]['cell'] = int(g.getText(y_cell, x_cell)) piece = self.state.next_piece piece[0] = y_cell piece[1] = x_cell else: assert (g.getText(y_cell, x_cell) == '-') if is_win(self.state.boards[point['y_board']][point['x_board']]): self.state.score[str(self.min_player)] += 1
class CompaniesAppGUI(AbsolutePanel): def __init__(self): AbsolutePanel.__init__(self) self.app = CompaniesApp() self.history = [] self.save = Button("save", self) self.selectDepartment = Button("select", self) self.selectEmployee = Button("select", self) self.edit = Button("edit", self) self.cut = Button("cut", self) self.back = Button("back", self) self.name = TextBox() self.address = TextBox() self.manager = TextBox() self.departments = ListBox(Size=("100%"), VisibleItemCount="5") self.employees = ListBox(Size=("100%"), VisibleItemCount="5") self.total = TextBox() self.errors = VerticalPanel() self.grid = Grid() self.allPanels = VerticalPanel() self.allPanels.add(self.grid) self.allPanels.add(self.errors) self.add(self.allPanels) self.initCompanyGUI() def onClick(self, sender): self.errors.clear() if sender == self.cut: self.current.cut() self.total.setText(self.current.total()) if sender == self.save: if self.current.__class__.__name__ == "Employee": if self.validateEmployee(self.current.id, self.name.getText(), self.address.getText(), self.total.getText()) == True: self.current.save(self.name.getText(), self.address.getText(), float(self.total.getText())) else: if self.validateDepartment(self.current.id, self.name.getText()) == True: self.current.save(self.name.getText()) if sender == self.selectDepartment: if (self.departments.getSelectedIndex() > -1): self.history.append(self.current) self.current = self.app.getDepartment(self.departments.getValue(self.departments.getSelectedIndex())) self.initDepartmentGUI() if sender == self.selectEmployee: if (self.employees.getSelectedIndex() > -1): self.history.append(self.current) self.current = self.app.getEmployee(self.employees.getValue(self.employees.getSelectedIndex())) self.initEmployeeGUI() if sender == self.edit: self.history.append(self.current) self.current = self.current.getManager() self.initEmployeeGUI() if sender == self.back: if len(self.history) > 0: self.current = self.history.pop() if self.current.__class__.__name__ == "Company": self.initCompanyGUI() else: self.initDepartmentGUI() def validateDepartment(self, index, name): valid = True if name == "": self.errors.add(Label("- Enter a valid name, please.")) valid = False for item in self.app.departments: if item.id != index and name == item.name: self.errors.add(Label("- There is already a department with the same name. Enter a valid name, please.")) valid = False return valid def validateEmployee(self, index, name, address, salary): valid = True if name == "": self.errors.add(Label("- Enter a valid name, please.")) valid = False if address == "": self.errors.add(Label("- Enter a valid address, please.")) valid = False if salary == "": self.errors.add(Label("- Enter a valid salary, please.")) valid = False try: float(salary) except ValueError: self.errors.add(Label("- The salary must be a number. Enter a valid salary, please.")) valid = False for item in self.app.employees: if item.id != index and name == item.name and item.address == address: self.errors.add(Label("- There is already an employee with the same name and address combination. Enter a valid name and address, please.")) valid = False return valid def initCompanyGUI(self): self.current = self.app.company self.grid.clear() self.grid.resize(4, 3) # row 1 self.grid.setWidget(0, 0, Label("Name:")) self.grid.setWidget(1, 0, Label("Department:")) self.grid.setWidget(2, 0, Label("Total:")) # row 2 self.grid.setWidget(0, 1, self.name) self.grid.setWidget(1, 1, self.departments) self.grid.setWidget(2, 1, self.total) # row 3 self.grid.setWidget(0, 2, self.save) self.grid.setWidget(1, 2, self.selectDepartment) self.grid.setWidget(2, 2, self.cut) self.name.setText(self.current.name) self.departments.clear() for item in self.current.departments: self.departments.addItem(item.name, item.id) if self.departments.getItemCount() > 0: self.departments.setSelectedIndex(0) self.total.setText(self.current.total()) def initDepartmentGUI(self): self.grid.clear() self.grid.resize(6, 3) # row 1 self.grid.setWidget(0, 0, Label("Name:")) self.grid.setWidget(1, 0, Label("Manager:")) self.grid.setWidget(2, 0, Label("Department:")) self.grid.setWidget(3, 0, Label("Employee:")) self.grid.setWidget(4, 0, Label("Total:")) # row 2 self.grid.setWidget(0, 1, self.name) self.grid.setWidget(1, 1, self.manager) self.grid.setWidget(2, 1, self.departments) self.grid.setWidget(3, 1, self.employees) self.grid.setWidget(4, 1, self.total) # row 3 self.grid.setWidget(0, 2, self.save) self.grid.setWidget(1, 2, self.edit) self.grid.setWidget(2, 2, self.selectDepartment) self.grid.setWidget(3, 2, self.selectEmployee) self.grid.setWidget(4, 2, self.cut) # back self.grid.setWidget(5, 2, self.back) self.name.setText(self.current.name) self.departments.clear() self.employees.clear() for item in self.current.departments: self.departments.addItem(item.name, item.id) if self.departments.getItemCount() > 0: self.departments.setSelectedIndex(0) for item in self.current.employees: if item.manager == 0: self.employees.addItem(item.name, item.id) else: self.manager.setText(item.name) if self.employees.getItemCount() > 0: self.employees.setSelectedIndex(0) self.total.setText(self.current.total()) def initEmployeeGUI(self): self.grid.clear() self.grid.resize(4, 3) # row 1 self.grid.setWidget(0, 0, Label("Name:")) self.grid.setWidget(1, 0, Label("Address:")) self.grid.setWidget(2, 0, Label("Salary:")) # row 2 self.grid.setWidget(0, 1, self.name) self.grid.setWidget(1, 1, self.address) self.grid.setWidget(2, 1, self.total) # row 3 self.grid.setWidget(0, 2, self.save) self.grid.setWidget(2, 2, self.cut) self.grid.setWidget(3, 2, self.back) self.name.setText(self.current.name) self.address.setText(self.current.address) self.total.setText(self.current.salary)
class GridWidget(AbsolutePanel): def __init__(self): self.state = State() self.game_round = 0 self.TD_CONSTS = { 'c3': 1., 'c2': 1., 'c1': 1., 'c6': 1., 'c5': 1., 'c4': 1. } self.CONSTS = { 'c3': .5, 'c2': 1., 'c1': 3., 'c6': .5, 'c5': .5, 'c4': .5 } self.BEST_CONSTANTS = { 'c3': 0.767944, 'c2': 1.049451, 'c1': 3.074038, 'c6': 0.220823, 'c5': 0.281883, 'c4': 0.605861 } self.ONES_CONSTS = { 'c3': 1., 'c2': 1., 'c1': 1., 'c6': 1., 'c5': 1., 'c4': 1. } AbsolutePanel.__init__(self) self.welcome_label = HTML( '<H2 align="center">Welcome to Meta-Tic-Tac-Toe!</H2>To watch the AI play itself, press either "begin game" button. Note: if there is a pop-up saying that the script is taking a long time to complete, this is not a bug - the AI is just taking a while to find the next move. Select the option to continue the script.', StyleName='margins_both') self.add(self.welcome_label) self.depth_limit = 2 self.train_td = Button("Begin game. Learning AI first!", self, StyleName='margins_left') self.add(self.train_td) self.train_static = Button("Begin game. Static AI first!", self, StyleName='margins_left') self.add(self.train_static) self.score_label = Label( "CURRENT SCORE: Learning AI: %d | Static AI: %d" % (0, 0), StyleName='margins_left') self.add(self.score_label) self.game_over_message = Label("", StyleName='margins_left') self.add(self.game_over_message) StyleSheetCssText(margins) self.increase_depth = Button("Increase ply search depth.", self) self.decrease_depth = Button("Decrease ply search depth.", self) self.depth_label = Label("Current depth is " + str(self.depth_limit) + ".") self.depth_grid = Grid(StyleName='margins_left') self.depth_grid.resize(1, 3) self.depth_grid.setBorderWidth(2) self.depth_grid.setCellPadding(9) self.depth_grid.setCellSpacing(1) self.add(self.depth_grid) self.depth_grid.setWidget(0, 0, self.decrease_depth) self.depth_grid.setWidget(0, 1, self.depth_label) self.depth_grid.setWidget(0, 2, self.increase_depth) # initialize the board grid: self.g = Grid(StyleName='margins_left') self.g.resize(3, 3) self.g.setBorderWidth(2) self.g.setCellPadding(9) self.g.setCellSpacing(1) self.init() self.add(self.g) # initialize the contstants adjustment grid: self.adj_grid = Grid(StyleName='margins_left') self.adj_grid.resize(7, 4) self.adj_grid.setBorderWidth(2) self.adj_grid.setCellPadding(9) self.adj_grid.setCellSpacing(1) self.init_constants_adj_grid() self.add(self.adj_grid) self.reset_constants = Button( "Reset all of Learning AI's constants to 1.", self, StyleName='margins_left') self.add(self.reset_constants) self.state_to_grid() def init_constants_adj_grid(self): '''Initializes the grid that allows the TD_CONSTS to be adjusted. ''' self.decr_buttons = {} self.adj_learning_labels = {} self.adj_static_labels = {} self.incr_buttons = {} td_keys = ['c1', 'c2', 'c3', 'c4', 'c5', 'c6'] learning_ai_header = Label("Constant for the learning AI.") self.adj_grid.setWidget(0, 0, learning_ai_header) static_ai_header = Label("Constants for the static AI.") self.adj_grid.setWidget(0, 2, static_ai_header) for i, key in enumerate(td_keys): j = i + 1 # off by one because of header... self.adj_learning_labels[key] = Label( "Constant %d: %f" % (key[1], self.TD_CONSTS[key])) self.adj_grid.setWidget(j, 0, self.adj_learning_labels[key]) self.decr_buttons[key] = Button('<', self) self.adj_grid.setWidget(j, 1, self.decr_buttons[key]) self.adj_static_labels[key] = Label("Constant %d: %f" % (key[1], self.CONSTS[key])) self.adj_grid.setWidget(j, 2, self.adj_static_labels[key]) self.incr_buttons[key] = Button('>', self) self.adj_grid.setWidget(j, 3, self.incr_buttons[key]) def init(self): '''Initializes the grid on which the game is played. ''' for y_board in range(3): for x_board in range(3): g = Grid() g.resize(3, 3) g.setBorderWidth(2) g.setCellPadding(9) g.setCellSpacing(1) for x_cell in range(3): for y_cell in range(3): b = Button('AI could play here.', self) b.point = { 'x_cell': x_cell, 'y_cell': y_cell, 'y_board': y_board, 'x_board': x_board } g.setWidget(y_cell, x_cell, b) self.add(g) self.g.setWidget(y_board, x_board, g) def start_new_game(self): #g.__init__() nope, can't use this :( g.state = State() g.game_over = False self.depthLimit = 2 self.human_first = True self.check_is_win() self.max_player = '-1' self.min_player = '-1' self.state_to_grid() def onClick(self, sender): self.check_adjusts(sender) if sender == self.reset_constants: self.TD_CONSTS = self.ONES_CONSTS self.sync_consts() if sender == self.increase_depth: self.depth_limit += 1 self.depth_label.setText("Current depth is " + str(self.depth_limit) + ".") if sender == self.decrease_depth: self.depth_limit -= 1 self.depth_label.setText("Current depth is " + str(self.depth_limit) + ".") if sender == self.train_td: self.state = State() self.static_ai_str = '2' self.td_ai_str = '1' self.state.next_piece = [1, 1, 1] Timer(250, notify=self.td_ai_turn) if sender == self.train_static: self.state = State() self.static_ai_str = '1' self.td_ai_str = '2' self.state.next_piece = [1, 1, 1] Timer(250, notify=self.static_ai_turn) def check_adjusts(self, sender): td_keys = ['c1', 'c2', 'c3', 'c4', 'c5', 'c6'] for key in td_keys: if self.incr_buttons[key] == sender: self.change_td_const(key, '+') if self.decr_buttons[key] == sender: self.change_td_const(key, '-') self.TD_CONSTS = normalize(self.TD_CONSTS) self.adj_learning_labels[key].setText( "Constant %d: %f" % (key[1], self.TD_CONSTS[key])) self.sync_consts() def change_td_const(self, key, sign): if sign == '+': self.CONSTS[key] += INCREMENT_AMOUNT elif sign == '-': self.CONSTS[key] -= INCREMENT_AMOUNT def sync_consts(self): """Sync td rates with the current state. """ td_keys = ['c1', 'c2', 'c3', 'c4', 'c5', 'c6'] for key in td_keys: self.adj_learning_labels[key].setText( "Constant %d: %f" % (key[1], self.TD_CONSTS[key])) self.adj_static_labels[key].setText("Constant %d: %f" % (key[1], self.CONSTS[key])) def check_is_win(self, last_position={}): self.state_to_grid( prev_x_board=last_position['x_board'], prev_y_board=last_position['y_board'], prev_x_cell=last_position['x_cell'], prev_y_cell=last_position['y_cell'], ) learning_ai_score = self.state.score[self.td_ai_str] static_ai_score = self.state.score[self.static_ai_str] self.score_label.setText( "CURRENT SCORE: Learning AI(%d): %d | Static AI(%d): %d" % (self.td_ai_str, learning_ai_score, self.static_ai_str, static_ai_score)) self.state.printInfo() if is_over(self.state): if learning_ai_score > static_ai_score: msg = "the learning AI won with score %d vs %d." % ( learning_ai_score, static_ai_score) elif learning_ai_score < static_ai_score: msg = "the static AI won with score %d vs %d." % ( static_ai_score, learning_ai_score) elif learning_ai_score == static_ai_score: msg = "the game ended in a tie." self.game_round += 1 game_over_message.setText("In game round " + str(self.game_round) + ", " + msg) return True else: return False def static_ai_turn(self): print "\n\nNaive AIs turn which plays the piece: ", self.state.next_piece[ 2] print "next piece is ", self.state.next_piece print "TD_CONSTS", self.TD_CONSTS (expectedUtility, next_state) = ab(self.state, self.CONSTS, depth_limit=self.depth_limit) last_position = find_last_move(self.state, next_state) self.state = next_state self.state.printInfo() over = self.check_is_win(last_position) print "back in static" if not over: self.pause_update = Timer(250, notify=self.td_ai_turn) else: return True def td_ai_turn(self): print "\n\nTD AI player starting turn. TD AI places the piece:", self.state.next_piece[ 2] print "TD_CONSTS after being adjusted are: ", self.TD_CONSTS # print, alpha-beta search etc.: (expectedUtility, state) = ab(self.state, self.TD_CONSTS, depth_limit=self.depth_limit) terminal_state = expectedUtility.terminal self.TD_CONSTS = td_learning(terminal_state, self.TD_CONSTS, self.state) self.sync_consts() # reflect the new TD_CONSTS in the game. last_position = find_last_move(self.state, state) self.state = state state.printInfo() print "TD_CONSTS after being adjusted are: ", self.TD_CONSTS over = self.check_is_win(last_position) print "back in td" print "Is over ", over if not over: return Timer(250, notify=self.static_ai_turn) else: return True def will_buttons(self, y_board, x_board): # first we determine if the next_piece points to a playable board. board = self.state.boards piece = list(self.state.next_piece) playable = True if is_win(board[piece[0]][piece[1]]) or is_full( board[piece[0]][piece[1]]): playable = False if (not is_win(board[y_board][x_board])) and (not is_full( board[y_board][x_board])): if not playable: return True if playable: return (y_board == piece[0]) and (x_board == piece[1]) return False def state_to_grid(self, prev_x_board=-1, prev_y_board=-1, prev_x_cell=-1, prev_y_cell=-1): board = self.state.boards for y_board in range(3): for x_board in range(3): # for this mini-grid, do i make buttons or dashes? will_make_buttons = self.will_buttons(y_board, x_board) g = Grid() g.resize(3, 3) g.setBorderWidth(2) g.setCellPadding(9) g.setCellSpacing(1) for y_cell in range(3): for x_cell in range(3): if board[y_board][x_board][y_cell][x_cell][ 'cell'] == 0: if will_make_buttons: b = HTML( '<p style="color:blue">AI %d could<br>play here.</p>' % (self.state.next_piece[2]), self) else: b = HTML('-') elif board[y_board][x_board][y_cell][x_cell][ 'cell'] == 1: if (prev_x_cell == x_cell and prev_y_cell == y_cell and prev_y_board == y_board and prev_x_board == x_board): b = HTML('<p style="color:red">1</p>') else: b = HTML('1') elif board[y_board][x_board][y_cell][x_cell][ 'cell'] == 2: if (prev_x_cell == x_cell and prev_y_cell == y_cell and prev_y_board == y_board and prev_x_board == x_board): b = HTML('<p style="color:red">2</p>') else: b = HTML('2') g.setWidget(y_cell, x_cell, b) self.add(g) self.g.setWidget(y_board, x_board, g)