Private loModel loModel = CreateObject("theModel") loModel.FillFNature() Local loView loView = CreateObject("theView") loView.SetupGrid(loModel) loView.Show() Local loChanger, loAgent, lnI For lnI = 1 to 5 loChanger = loModel.RandomArranger() loAgent = loView.NewAgent() loAgent.BorderColor = Rgb(0, 0, 255) BindEvent(loChanger, "Moved", loAgent, "Redraw") BindEvent(loChanger, "FinishedSquare", loAgent, "Recolor") EndFor For lnI = 1 to 5 loChanger = loModel.RandomChanger() loAgent = loView.NewAgent() BindEvent(loChanger, "Moved", loAgent, "Redraw") EndFor DO while loView.Visible Doevents loModel.Go() EndDo Define Class theModel as Session oChangers = .null. Function Init USE fnature USE nature In 0 Set Relation To Ceiling(Recno()/3) into nature this.oChangers = CreateObject("collection") Return Function FillFNature Rand(0) Local loRecord Scatter name loRecord Blank Local lnI Scan For lnI = 1 to 27 Store Int(Rand() * 10) To ('loRecord.f' + Transform(lnI)) EndFor Gather name loRecord EndScan Go top Return Function Go Local loObject, loException For each loObject in this.oChangers loObject.DoYoThang() EndFor Return Function RandomChanger Local loObject loObject = CreateObject("changer") loObject.nY = Rand27() loObject.nX = Rand27() loObject.nDX = Iif(loObject.nX = 1, -1, Iif(loObject.nX = 27, 1, RandN())) loObject.nDY = Iif(loObject.nY = 1, -1, Iif(loObject.nY = 27, 1, RandN())) this.oChangers.Add(loObject) Return loObject Function RandomArranger Local loObject loObject = CreateObject("arranger") loObject.nY = Rand9() loObject.nX = Rand9() loObject.nDX = Iif(loObject.nX = 1, -1, Iif(loObject.nX = 9, 1, RandN())) loObject.nDY = Iif(loObject.nY = 1, -1, Iif(loObject.nY = 9, 1, RandN())) this.oChangers.Add(loObject) Return loObject EndDefine Define Class changer As Custom nX = 1 nY = 1 nDX = 1 nDY = 1 nLastValue = 1 Function DoYoThang With this * Check to see if we're at an edge and need to change direction If .nX = 1 or .nX = 27 .nDX = .nDX * -1 EndIf If .nY = 1 or .nY = 27 .nDY = .nDY * -1 EndIf .nX = .nX + .nDX .nY = .nY + .nDY Go (.nY) Local lnLastValue lnLastValue = .nLastValue .nLastValue = eval('f' + Transform(.nX)) replace ('f' + Transform(.nX)) with Mod(.nLastValue + lnLastValue, 10) EndWith RaiseEvent(this, "Moved", this) Return Function Moved Lparameters toChanger Return EndDefine Define Class Arranger As Custom nX = 1 nY = 1 nDX = 1 nDY = 1 nSY = 1 nSX = 1 nDSY = 1 nLastValue = 1 nSquareTotal = 0 nCurrentValue = 0 Function DoYoThang With this .nSquareTotal = .nSquareTotal + .nCurrentValue * if we're not done with this vertical section keep moving If (.nSY < 3 and .nDSY = 1) or (.nSY > 1 and .nDSY = -1) .nSY = .nSY + .nDSY Else * if we're done with this vertical section * if we're not done with this square move keep moving If (.nSX < 3 and .nDX = 1) or (.nSX > 1 and .nDX = -1) .nSX = .nSX + .nDX .nDSY = .nDSY * -1 Else * if we're done with this square update the color RaiseEvent(this, "FinishedSquare", this) .nSquareTotal = 0 * if we're not done with this horizontal section keep moving If (.nX < 9 and .nDX = 1) or (.nX > 1 and .nDX = -1) .nX = .nX + .nDX .nSX = Iif(.nDX = 1, 1, 3) .nDSY = .nDSY * -1 Else * if we're done with this horizontal section .nDX = .nDX * -1 .nSX = Iif(.nDX = 1, 1, 3) * If we're at a top or bottom change direction If (.nY = 9 and .nDY = 1) or (.nY = 1 and .nDY = -1) .nDY = .nDY * -1 EndIf .nY = .nY + .nDY .nSY = 1 EndIf EndIf EndIf Go ((.nY - 1) * 3 + .nSY) Local lnLastValue, lnCol lnLastValue = .nLastValue lnCol = (.nX - 1) * 3 + .nSX .nLastValue = eval('f' + Transform(lnCol)) .nCurrentValue = Mod(.nLastValue + lnLastValue, 10) replace ('f' + Transform(lnCol)) with .nCurrentValue EndWith RaiseEvent(this, "Moved", this) Return Function Moved Lparameters toChanger Return Function FinishedSquare Lparameters tnColor Return EndDefine Function Rand27 Return Int(Rand() * 27) + 1 Function Rand9 Return Int(Rand() * 9) + 1 Function Rand1 Return Iif(Rand() < .50, 0, 1) Function RandN Return Iif(Rand() < .50, -1, 1) * This is the view... la lal la la la... DEFINE CLASS theView AS form Top = 0 Left = 0 Height = 560 Width = 996 DoCreate = .T. Caption = "Form1" Name = "Form1" ADD OBJECT og AS grid WITH ; Height = 518, ; Left = 0, ; ScrollBars = 0, ; Top = 0, ; Width = 996, ; Name = "oG", ; deletemark = .f., ; recordmark = .f., ; Highlight = .F. ADD OBJECT cmdNature AS CommandButton WITH ; Height = 28, ; Left = 30, ; Top = 530, ; Width = 90, ; Caption = "NATURE" ADD OBJECT cmdClose AS CommandButton WITH ; Height = 28, ; Left = 140, ; Top = 530, ; Width = 90, ; Caption = "Close" Procedure cmdClose.Click thisform.Hide() Return Procedure cmdNature.Click If this.Caption = "NATURE" For lnI = 1 to 27 thisform.og.Columns[lnI].DynamicBackColor = "nature.f" + Transform(Ceiling(lnI/3)) EndFor this.Caption = "NO NATURE" Else For lnI = 1 to 27 thisform.og.Columns[lnI].DynamicBackColor = "" EndFor this.Caption = "NATURE" EndIf EndProc PROCEDURE setupgrid Lparameters toModel this.DataSessionId = toModel.DataSessionId this.oG.RecordSource = "fnature" this.oG.ColumnCount = 0 For lnI = 1 to 27 this.oG.AddColumn(lnI) this.oG.Columns[lnI].Header1.Caption = Transform(lnI) this.oG.Columns[lnI].Header1.Alignment = 2 this.oG.Columns[lnI].Width = 35 this.oG.Columns[lnI].Alignment = 2 this.oG.Columns[lnI].ControlSource = "fnature.f" + Transform(lnI) EndFor ENDPROC Function newAgent Lparameters tnColor Local lcName, loO lcName = Sys(2015) this.AddObject(lcName, "agentshape") loO = Evaluate("this." + lcName) loO.Visible = .t. Return loO ENDDEFINE Define Class agentShape as Shape Curvature = 99 BackStyle = 0 BorderWidth=4 BorderColor = 255 Width = 20 Function Redraw Lparameters toChanger DO case Case Upper(toChanger.Class) = "CHANGER" this.Left = ((toChanger.nX - 1 ) * 36) + 8 this.Top = ((toChanger.ny - 1)* 18) + 20 Case Upper(toChanger.Class) = "ARRANGER" this.Left = ((toChanger.nX - 1) * 36 * 3) + 8 + ((toChanger.nSX - 1) * 36) this.Top = ((toChanger.ny - 1)* 18 * 3) + 20 + ((toChanger.nSY - 1) * 18) EndCase thisform.Refresh() Return Function Recolor Lparameters toArranger Go (toArranger.nY ) in nature replace ('f' + Transform(toArranger.nX)) with toArranger.nSquareTotal * 207126.11 in nature * thisform.Refresh() Return EndDefineThe first thing you see is a white grid with numbers and red and blue circles moving around. The numbers are just numbers and don't represent anything in particular. (This isn't a model of nature, it is an arbitrary model designed to demonstrate the idea that we can look at a computer simulation by watching all of the statements produced by the program or a generalized view of the statements, and that each set of changing statements produces its own version of time.)