Hey everyone, find the verse code at the bottom of this message!!!
I’d love to introduce you to something a little different — Solitaire Switch, a fresh take on card-based gameplay that’s as much about logic and momentum as it is about luck. It started as a prototype to explore card mechanics and mouse interactions… but it’s grown into a quirky, buggy, and surprisingly addictive little game that’s ready for you to try.
Your goal? Simple in theory — brutal in practice.
Play every single card from the deck onto the board. Leave even one card behind in any hand, and it’s game over. The real challenge isn’t just your own strategy — it’s managing the rhythm of the table and working with (or around) the indifferent AI that plays strictly by logic. Left on their own, four AIs win only about 1 in 10 games. You? You can do better.
Controls:
Mouse: Aim-and-click, with adjustable sensitivity.
Controller: Full gamepad support with intuitive UI navigation.
Yes, it’s buggy. Yes, it’s rough around the edges. But underneath it all is a playable card game with real strategic bite, emergent strategies, and a satisfying challenge — especially if you enjoy solving puzzles, mastering patterns, or out-thinking the system.
If any of that sounds like your kind of fun, give Solitaire Switch a try! It’s not polished, but it’s experimental, it’s playable, and once it clicks… it’s hard to put down.
P͟l͟a͟y͟ ͟i͟t͟ ͟h͟e͟r͟e͟:͟ 1217-1574-4756
Thanks for checking it out, if there is interest then expect to see an improved version coming soon with my future projects!
Verse Code
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /Fortnite.com/Characters }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /UnrealEngine.com/Temporary/UI }
using { /Verse.org/Assets }
using { /Verse.org/Random }
PolarToCartesian(X:float, Y:float, Z:float):vector3 := return vector3{X:=Z, Y:=X*5.3333333333333333, Z:=Y*6.0}
PolarToCartesianWorld(X:float, Y:float, Z:float):vector3 := return vector3{X:=Z, Y:=X*5.3333333333333333, Z:=1024.0+Y*6.0}
Tree := interface:
GetZone(InX:float,InY:float):?BlankZone
BlankZone := class<unique>(Tree):
XMin:float
XMax:float
YMin:float
YMax:float
GetZone<override>(InX:float,InY:float):?BlankZone:=return option{Self}
SelectorInteraction():void:=return
CursorLeftFocus(Pointer:CursorHandler):void:=return
CursorEnteredFocus(Pointer:CursorHandler):void:=return
CursorClick(Pointer:CursorHandler, X:float, Y:float):void:=return
CursorRelease(Pointer:CursorHandler, X:float, Y:float):void:=return
DropHoldable(Obj:Grab_Obj):void:=
Obj.ReturnHome()
DropHoldable(Obj:Grab_Obj, X:float, Y:float):void:=DropHoldable(Obj)
RemoveHomeLink(Obj:Grab_Obj):void:=return
SelectorUp():void:=return
SelectorDown():void:=return
SelectorLeft():void:=return
SelectorRight():void:=return
GetNextZone(BaseTree:Tree,X:float, Y:float):?BlankZone:=
if(XMin <= X <= XMax and YMin <= Y <= YMax){return false}
else{return BaseTree.GetZone(X,Y)}
GameToggleButtonZone := class(BlankZone, Focusable):
BackRef:CCGDemoController
BaseProp:creative_prop
ButtonPos:vector3
LeftLink:BlankZone
GetFocalTransform<override>()<transacts>:transform := return transform{Translation := ButtonPos ,Scale :=vector3{X:=1.0, Y:=1.5, Z:=0.3}, Rotation := IdentityRotation()}
CursorLeftFocus<override>(Pointer:CursorHandler):void:=
BaseProp.SetMaterial(Materials.PlayGreen1)#spawn{BaseProp.MoveTo(transform{Translation := vector3{X:=-960.0, Y:=-464.5, Z:=1172.5}, Scale := vector3{X:=1.0, Y:=207.0, Z := 297.0}},0.5)}
Pointer.UpdateStyle(CursorStyle.Standard)
CursorEnteredFocus<override>(Pointer:CursorHandler):void:=
BaseProp.SetMaterial(Materials.SideGreen)#spawn{BaseProp.MoveTo(transform{Translation := vector3{X:=-960.0, Y:=-464.5, Z:=1172.5}, Scale := vector3{X:=1.0, Y:=414.0, Z := 594.0}},0.5)}
Pointer.UpdateStyle(CursorStyle.Pointing)
CursorClick<override>(Pointer:CursorHandler, X:float, Y:float):void:=SelectorInteraction()
SelectorInteraction<override>():void:=
BackRef.ToggleInfoState()
SelectorLeft<override>():void:=
if(Selector := BackRef.Controller.SelectorRef?; Left := Focusable[LeftLink]){Selector.SetFocus(Left)}
InfoToggleButtonZone := class(BlankZone, Focusable):
BackRef:CCGDemoController
BaseProp:creative_prop
ButtonPos:vector3
LeftLink:BlankZone
GetFocalTransform<override>()<transacts>:transform := return transform{Translation := ButtonPos ,Scale :=vector3{X:=1.0, Y:=1.5, Z:=0.3}, Rotation := MakeRotationFromYawPitchRollDegrees(180.0,0.0,0.0)}
CursorLeftFocus<override>(Pointer:CursorHandler):void:=
BaseProp.SetMaterial(Materials.PlayGreen1)#spawn{BaseProp.MoveTo(transform{Translation := vector3{X:=-960.0, Y:=-464.5, Z:=1172.5}, Scale := vector3{X:=1.0, Y:=207.0, Z := 297.0}},0.5)}
Pointer.UpdateStyle(CursorStyle.Standard)
CursorEnteredFocus<override>(Pointer:CursorHandler):void:=
BaseProp.SetMaterial(Materials.SideGreen)#spawn{BaseProp.MoveTo(transform{Translation := vector3{X:=-960.0, Y:=-464.5, Z:=1172.5}, Scale := vector3{X:=1.0, Y:=414.0, Z := 594.0}},0.5)}
Pointer.UpdateStyle(CursorStyle.Pointing)
CursorClick<override>(Pointer:CursorHandler, X:float, Y:float):void:=SelectorInteraction()
SelectorInteraction<override>():void:=
BackRef.ToggleInfoState()
SelectorRight<override>():void:=
if(Selector := BackRef.Controller.SelectorRef?; Left := LevelZone[LeftLink]):
Selector.SetFocus(Left)
if(LZone := LevelZone[LeftLink]):
LZone.EnteredZone()
LevelZone := class(BlankZone, Focusable):
BackRef:CCGDemoController
PortalLink:matchmaking_portal_device
Frame:creative_prop
PictureMat:material
VideoMat:material
Pos:vector3
var LeftLink:BlankZone := BlankZone{XMin := 0.0, XMax := 0.0, YMin := 0.0, YMax := 0.0}
var RightLink:BlankZone := BlankZone{XMin := 0.0, XMax := 0.0, YMin := 0.0, YMax := 0.0}
GetFocalTransform<override>()<transacts>:transform := transform{Translation := Pos ,Scale :=vector3{X:=1.0, Y:=1.75, Z:=0.75}, Rotation := MakeRotationFromYawPitchRollDegrees(180.0,0.0,0.0)}
CursorLeftFocus<override>(Pointer:CursorHandler):void:=LeftZone()
CursorEnteredFocus<override>(Pointer:CursorHandler):void:=EnteredZone()
SelectorLeft<override>():void:=
if(Selector := BackRef.Controller.SelectorRef?; Left := Focusable[LeftLink]):
Selector.SetFocus(Left)
if(LZone := LevelZone[LeftLink]):
LeftZone()
LZone.EnteredZone()
SelectorRight<override>():void:=
if(Selector := BackRef.Controller.SelectorRef?; Right := Focusable[RightLink]):
Selector.SetFocus(Right)
if(LZone := LevelZone[RightLink]):
LeftZone()
LZone.EnteredZone()
EnteredZone():void:=
PortalLink.Enable()
BackRef.ShowInteract.Enable()
BackRef.HideInteract.Disable()
Frame.SetMaterial(VideoMat)
LeftZone():void:=
PortalLink.Disable()
BackRef.HideInteract.Enable()
BackRef.ShowInteract.Disable()
Frame.SetMaterial(PictureMat)
PlayZone := class(BlankZone):
BackRef:CCGDemoController
var PhysicalStack:[]Physical_Card := array{}
var VirtualStack:[]Virtual_Card := array{}
BaseProp:creative_prop
CursorLeftFocus<override>(Pointer:CursorHandler):void:=BaseProp.SetMaterial(Materials.PlayGreen1)#spawn{BaseProp.MoveTo(transform{Translation := vector3{X:=-960.0, Y:=-464.5, Z:=1172.5}, Scale := vector3{X:=1.0, Y:=207.0, Z := 297.0}},0.5)}
CursorEnteredFocus<override>(Pointer:CursorHandler):void:=BaseProp.SetMaterial(Materials.SideGreen)#spawn{BaseProp.MoveTo(transform{Translation := vector3{X:=-960.0, Y:=-464.5, Z:=1172.5}, Scale := vector3{X:=1.0, Y:=414.0, Z := 594.0}},0.5)}
DropHoldable<override>(Obj:Grab_Obj):void:=DropHoldable(Obj, -87.28125+GetRandomFloat(-40.0, 40.0),24.625+GetRandomFloat(-12.0, 12.0))
DropHoldable<override>(Obj:Grab_Obj, X:float, Y:float):void:=
if(Card := Physical_Card[Obj], Card.HomeZone = BlankZone[Self]){return}
else if(Sol := SolitairSwitch[BackRef.GameSession],Card := Physical_Card[Obj], Card.HomeZone = Sol.CurrentPlayer(1),BackRef.Controller.SelectorRef?.Lock = false, Sol.PickupState = 0 or Card.Value = 13 or Card.Value = 2):
Turn := BackRef.GameSession.ApplyTurn(BackRef.HandArea,option{Card})
if(Turn = true):
AddCard(Card, X, Y)
else if(Card := Physical_Card[Obj],BZone := Card.HomeZone, BZone <> BackRef.HandArea):
AddCard(Card, X, Y)
if(Card := Physical_Card[Obj]):
Card.ReturnHome()
AddCard(Card:Physical_Card, X:float, Y:float):void:=
if(PhysicalStack.Length > 15, Transfer := PhysicalStack.Slice[0,8], Rest := PhysicalStack.Slice[8]):
for(Index:=0..Rest.Length-1,MoveCard:=Rest[Index]){Pos:=MoveCard.CardProp.GetTransform().Translation;spawn{MoveCard.MoveToRightUp(vector3{X:=-962.0-(Index*1.0), Y:=Pos.Y, Z:= Pos.Z},vector3{X:=1.0,Y:=1.0,Z:=1.0})}}
set PhysicalStack = Rest
set VirtualStack += for(RemoveCard:Transfer){RemoveCard.Virtualise()}
set PhysicalStack += array{Card}
if(Card.CardProp.TeleportTo[Card.CardProp.GetTransform().Translation-vector3{X:=103.5}, Card.Rotation]):
spawn:
Card.MoveToRightUp(vector3{X:=-962.0-(PhysicalStack.Length*1.0), Y:=((X+87.28125-16.132653)) - 368.5, Z:= ((Y-24.625)) + 1108.5},vector3{X:=1.0,Y:=1.0,Z:=1.0})
Card.SetHome(Self)
ReturnCards():[]Virtual_Card:=
Out := VirtualStack + for(Card:PhysicalStack){Card.Virtualise()}
set PhysicalStack = array{}
set VirtualStack = array{}
return Out
HandZone := class(BlankZone, Focusable):
BackRef:CCGDemoController
BaseProp:creative_prop
var HandArray:[]Physical_Card := array{}
var SelectedCard:?Physical_Card := false
var LastIndex:?int := false
UpdateDeckPlacement():void:=if(HandArray.Length <> 0){for(Index := 0..HandArray.Length; Card := HandArray[Index]){spawn{Card.MoveToRightUp(vector3{X:=-962.0, Y:=(Index*207.0)-851.5, Z:=640.0})}}}
IsOverCard(X:float):void:=
if(Cursor := BackRef.Controller.CursorRef?){if(Index := Floor[(X+180.0)*0.02576489533],Index<=HandArray.Length-1):
if(HasIndex := LastIndex?):
if(Index <> LastIndex?; Card := HandArray[Index]):
set LastIndex = option{Index}
BackRef.UpdateSelected.Signal(option{Card})
else if(Card := HandArray[Index]):
set LastIndex = option{Index}
BackRef.UpdateSelected.Signal(option{Card})
Cursor.UpdateStyle(CursorStyle.Pointing)
else{Cursor.UpdateStyle(CursorStyle.Standard)}}
RemoveCard(OldCard:Virtual_Card):void:=
if(SelectedCard? = OldCard){set SelectedCard = false}
set HandArray = for(Card:HandArray, Card <> OldCard){Card}
UpdateDeckPlacement()
GetCardPosition(Card:Physical_Card)<transacts>:vector3:=
for(Index := 0..HandArray.Length-1,TCard:=HandArray[Index], TCard = Card){return vector3{X:=-963.0, Y:=(Index*207.0)-851.5, Z:=640.0}}
return vector3{}
GetFocalTransform<override>()<transacts>:transform :=
if(Card := SelectedCard?){return transform{Translation := GetCardPosition(Card) ,Scale :=vector3{X:=1.0, Y:=1.0, Z:=1.0}, Rotation := IdentityRotation()}}
else if(Card := HandArray[0]){set SelectedCard = option{Card}; return transform{Translation := GetCardPosition(Card) ,Scale :=vector3{X:=1.0, Y:=1.0, Z:=1.0}, Rotation := IdentityRotation()}}
return transform{}
SelectorInteraction<override>():void:=
if(Sol := SolitairSwitch[BackRef.GameSession],Self = Sol.CurrentPlayer(1)):
if(Card := SelectedCard?, Play := PlayZone[BackRef.PlayArea]):
SelectorRight()
RemoveCard(Card)
Play.DropHoldable(Card)
SelectorUp<override>():void:=if(Selector := BackRef.Controller.SelectorRef?, DeckA := DeckZone[BackRef.DeckArea]){Selector.SetFocus(DeckA)}
SelectorDown<override>():void:=if(Selector := BackRef.Controller.SelectorRef?){Selector.SetFocus(Self)}
SelectorRight<override>():void:=
if(Selector := BackRef.Controller.SelectorRef?):
if(PrevSelected := SelectedCard?,var Prev:Physical_Card = HandArray[0]):
if(HandArray.Length > 1 and Prev <> PrevSelected):
for(Index := 1..HandArray.Length-1, NextCard := HandArray[Index]):
if(NextCard = PrevSelected):
set SelectedCard = option{Prev}
if(Index-1 <> LastIndex; Card := HandArray[Index-1]):
set LastIndex = option{Index-1}
BackRef.UpdateSelected.Signal(option{Card})
return Selector.SetFocus(Self)
else:
set Prev = NextCard
set SelectedCard = option{Prev}
if(0 <> LastIndex; Card := HandArray[0]):
set LastIndex = option{0}
BackRef.UpdateSelected.Signal(option{Card})
return Selector.SetFocus(Self)
else if(Index :=Floor[HandArray.Length*0.5], First := HandArray[Index]):
set SelectedCard = option{First}
if(Index <> LastIndex; Card := HandArray[Index]):
set LastIndex = option{Index}
BackRef.UpdateSelected.Signal(option{Card})
return Selector.SetFocus(Self)
SelectorLeft<override>():void:=
if(Selector := BackRef.Controller.SelectorRef?):
if(PrevSelected := SelectedCard?,var Prev:Physical_Card = HandArray[HandArray.Length-1]):
if(HandArray.Length > 1 and Prev <> PrevSelected):
for(Index := 2..HandArray.Length, AltIndex := HandArray.Length-Index, NextCard := HandArray[AltIndex]):
if(NextCard = PrevSelected):
set SelectedCard = option{Prev}
if(AltIndex+1 <> LastIndex; Card := HandArray[AltIndex+1]):
set LastIndex = option{AltIndex+1}
BackRef.UpdateSelected.Signal(option{Card})
return Selector.SetFocus(Self)
else:
set Prev = NextCard
set SelectedCard = option{Prev}
if(0 <> LastIndex; Card := HandArray[0]):
set LastIndex = option{0}
BackRef.UpdateSelected.Signal(option{Card})
return Selector.SetFocus(Self)
else if(Index :=Floor[HandArray.Length*0.5], First := HandArray[Index]):
set SelectedCard = option{First}
if(Index <> LastIndex; Card := HandArray[Index]):
set LastIndex = option{Index}
BackRef.UpdateSelected.Signal(option{Card})
return Selector.SetFocus(Self)
CursorLeftFocus<override>(Pointer:CursorHandler):void:=
if(Cursor := BackRef.Controller.CursorRef?):
set LastIndex = false
Cursor.UpdateStyle(CursorStyle.Standard)
CursorEnteredFocus<override>(Pointer:CursorHandler):void:=return
CursorRelease<override>(Pointer:CursorHandler, X:float, Y:float):void:=return
GetZone<override>(X:float, Y:float):?BlankZone:=
IsOverCard(X)
return (super:)GetZone(X, Y)
CursorClick<override>(Pointer:CursorHandler, X:float, Y:float):void:=
if(Cursor := BackRef.Controller.CursorRef?, Index := Floor[(X+180.0)*0.02576489533], Card := HandArray[Index]):
RemoveCard(Card)
Offset := PolarToCartesian((((Index*1.0))*38.8125)-(X+160.59375),-64.58333333-Y,0.0)
Cursor.CursorHold(option{(Card,Offset)})
DropHoldable<override>(Obj:Grab_Obj, X:float, Y:float):void:=DropHoldable(Obj)
DropHoldable<override>(Obj:Grab_Obj):void:=
if(Card := Physical_Card[Obj], BZone := BlankZone[Card.HomeZone]):
set HandArray += array{Card}
Card.SetHome(Self)
UpdateDeckPlacement()
DealCard(Card:Physical_Card):void:=
Card.SetHome(Self)
spawn{Card.MoveToRightUp(vector3{X:=-962.0, Y:=(HandArray.Length*207.0)-851.5, Z:=640.0})}
set HandArray += array{Card}
ReturnCards():[]Virtual_Card:=
Out := for(Card:HandArray){Card.Virtualise()}
set HandArray = array{}
return Out
AIHandZone := class(HandZone):
XMax<override>:float := 0.0
YMax<override>:float := 0.0
BaseProp<override>:creative_prop := creative_prop{}
UpdateDeckPlacement<override>():void:=if(HandArray.Length <> 0){for(Index := 0..HandArray.Length; Card := HandArray[Index]){spawn{Card.MoveToRightUp(vector3{X:=-961.0, Y:=(Index*103.5)+XMin, Z:=YMin}, vector3{X:=1.0,Y:=0.5,Z:=0.5})}}}
RemoveHomeLink<override>(Obj:Grab_Obj):void:=if(OldCard := Physical_Card[Obj]){set HandArray = for(Card:HandArray, Card <> OldCard){Card};UpdateDeckPlacement()}
CursorLeftFocus<override>(Pointer:CursorHandler):void:=return
CursorEnteredFocus<override>(Pointer:CursorHandler):void:=return
GetZone<override>(X:float, Y:float):?BlankZone:=return option{Self}
CursorClick<override>(Pointer:CursorHandler, X:float, Y:float):void:=return
DropHoldable<override>(Obj:Grab_Obj, X:float, Y:float):void:=DropHoldable(Obj)
DropHoldable<override>(Obj:Grab_Obj):void:=
if(Card := Physical_Card[Obj], BZone := BlankZone[Card.HomeZone]):
Card.SetHome(Self)
set HandArray += array{Card}
UpdateDeckPlacement()
ChooseNextCard(isTestCard:?Virtual_Card, Play:GameState):?Virtual_Card:=
if(TestCard:=isTestCard?):
case(Play):
GameState.Play2orPickup2 => block{for(Card:HandArray, Card.Value = 2){return option{Card}};return false}
GameState.Play7andDiamond => block{for(Card:HandArray, Card.Suit = CardType.Diamond){return option{Card}};return false}
GameState.Play7andHeart => block{for(Card:HandArray, Card.Suit = CardType.Heart){return option{Card}};return false}
GameState.Play7andSpade => block{for(Card:HandArray, Card.Suit = CardType.Spade){return option{Card}};return false}
GameState.Play7andClub => block{for(Card:HandArray, Card.Suit = CardType.Club){return option{Card}};return false}
GameState.Play8orSkip => block{for(Card:HandArray, Card.Value = 8){return option{Card}};return false}
GameState.PlayKingorPickup5 => block{for(Card:HandArray, Card.Value = 13){return option{Card}};return false}
_ => return PickStandard(TestCard)
else:
return false
PickStandard(TestCard:Virtual_Card):?Virtual_Card:=
for(Card:HandArray, TestCard.Suit = Card.Suit and TestCard.Value = 7){return option{Card}}
for(Card:HandArray, TestCard.Suit = Card.Suit or (TestCard.Value = Card.Value <> 1)){return option{Card}}
var Aces:[]Virtual_Card := array{}
var SuitCounts:[CardType]int := map{CardType.Diamond => 0,CardType.Heart => 0,CardType.Spade => 0,CardType.Club => 0}
for(Card:HandArray){if(Card.Value = 1){set Aces+=array{Card}}else{if(set SuitCounts[Card.Suit]+=1){}}}
if(var LargestCard:Virtual_Card := Aces[0]):
if(Aces.Length>1):
for(Index:=1..Aces.Length, TestAce := Aces[Index], SuitCounts[TestAce.Suit]>SuitCounts[LargestCard.Suit]){set LargestCard = TestAce}
return option{LargestCard}
return false
DealCard<override>(Card:Physical_Card):void:=
Card.SetHome(Self)
spawn{Card.MoveToRightUp(vector3{X:=-961.0, Y:=(HandArray.Length*103.5)+XMin, Z:=YMin}, vector3{X:=1.0,Y:=0.5,Z:=0.5})}
set HandArray += array{Card}
DeckZone := class(BlankZone, Focusable):
BackRef:CCGDemoController
var TopCard:?Physical_Card
var NextCard:?Physical_Card
Deck:Card_Deck
var hasClick:?vector2:=false
GetFocalTransform<override>()<transacts>:transform := return transform{Translation := Deck.DeckPosition + vector3{X:=1.0} ,Scale :=vector3{X:=1.0, Y:=1.0, Z:=1.0}, Rotation := IdentityRotation()}
SetNewDeck(Cards:[]Virtual_Card):void:=
set TopCard = false
set NextCard = false
set Deck.VirtualDeck = Cards
GetCardCount()<transacts>:int:=if(TopCard?){if(NextCard?){Deck.GetCardCount()+2}else{Deck.GetCardCount()+1}}else{Deck.GetCardCount()}
SelectorUp<override>():void:=if(Selector := BackRef.Controller.SelectorRef?){Selector.SetFocus(Self)}
SelectorDown<override>():void:=
if(Select := BackRef.Controller.SelectorRef?, DeckA := HandZone[BackRef.HandArea]):
if(not DeckA.SelectedCard?,Index :=Floor[DeckA.HandArray.Length*0.5], First := DeckA.HandArray[Index]):
set DeckA.SelectedCard = option{First}
if(Index <> DeckA.LastIndex; Card := DeckA.HandArray[Index]):
set DeckA.LastIndex = option{Index}
BackRef.UpdateSelected.Signal(option{Card})
Select.SetFocus(DeckA)
SelectorRight<override>():void:=if(Select := BackRef.Controller.SelectorRef?, DeckA := Focusable[BackRef.GameToggle]){Select.SetFocus(DeckA)}
SelectorInteraction<override>():void:=
if(Sol := SolitairSwitch[BackRef.GameSession],SZone := HandZone[BackRef.HandArea], SZone = Sol.CurrentPlayer(1)){
BackRef.GameSession.ApplyTurn(SZone,false)
}
CursorEnteredFocus<override>(Pointer:CursorHandler):void:=Pointer.UpdateStyle(CursorStyle.Pointing)
CursorLeftFocus<override>(Pointer:CursorHandler):void:=Pointer.UpdateStyle(CursorStyle.Standard)
ClickDelay()<suspends>:void:=
Sleep(0.5)
set hasClick = false
CursorClick<override>(Pointer:CursorHandler, X:float, Y:float):void:=
if(Sol := SolitairSwitch[BackRef.GameSession],SZone := HandZone[BackRef.HandArea], SZone = Sol.CurrentPlayer(1)){
if(Sol.State = GameState.Play2orPickup2 or Sol.State = GameState.PlayKingorPickup5,Card := TopCard?, SZone.HandArray.Length<8):
if(Click := hasClick?):
if(Distance(vector2{X:=X, Y:=Y},Click) < 1.5):
BackRef.GameSession.ApplyTurn(SZone,false)
return
set hasClick = option{vector2{X:=X, Y:=Y}}
spawn{ClickDelay()}
Offset := PolarToCartesian(-X,24.666666667-Y,0.0)
Pointer.CursorHold(option{(Card,Offset)})
else:
BackRef.GameSession.ApplyTurn(SZone,false)
}
CursorRelease<override>(Pointer:CursorHandler, X:float, Y:float):void:=return
RemoveHomeLink<override>(Obj:Grab_Obj):void:=
if(Card := Physical_Card[Obj]):
if(NCard := NextCard?):
if(Sol := SolitairSwitch[BackRef.GameSession], SZone := BlankZone[Sol.HandAreas[0]] and Sol.PickupState > 0):#, CurrentCount := Sol.PickupCount?):
Sol.DecrementPickupCount()
spawn{NCard.MoveToBackUp(Deck.DeckPosition+vector3{X:=1.0},0.05)}
set TopCard = NextCard
set NextCard = Deck.LoadNextCard(Self)
else:
if(Sol := SolitairSwitch[BackRef.GameSession], SZone := BlankZone[Sol.HandAreas[0]]):#, CurrentCount := Sol.PickupCount?):
Sol.RemovePickupCount()
Sol.ApplyTurn(SZone,false)
set TopCard = false
DropHoldable<override>(Obj:Grab_Obj, X:float, Y:float):void:= DropHoldable(Obj)
DropHoldable<override>(Obj:Grab_Obj):void:=
if(Card := Physical_Card[Obj]):
if(Card = TopCard?):
spawn{Card.MoveToBackUp(Deck.DeckPosition)}
else:
Card.ReturnHome()
QuickShuffle(Count:int):void:=
if(Card1 := TopCard?):
if(Card2:=NextCard?):
Deck.AddPhysicalCards(array{Card1,Card2})
else:
Deck.AddPhysicalCards(array{Card1})
else if(Card2:=NextCard?):
Deck.AddPhysicalCards(array{Card2})
for(Index:=0..Count-1):
if(DeckSlice := Floor[Deck.VirtualDeck.Length*0.5], var Deck1:[]Virtual_Card := Deck.VirtualDeck.Slice[0,DeckSlice], var Deck2:[]Virtual_Card := Deck.VirtualDeck.Slice[DeckSlice]):
set Deck.VirtualDeck = array{}
loop:
if(Deck1.Length =0 and Deck2.Length = 0):
break
else if(Deck1.Length = Deck2.Length):
if(GetRandomInt(0,1)=0;Select := Deck1[0], Rest := Deck1.Slice[1]):
set Deck.VirtualDeck += array{Select}
set Deck1 = Rest
else if(Select := Deck2[Deck2.Length-1], Rest := Deck2.Slice[0,Deck2.Length-1]):
set Deck.VirtualDeck += array{Select}
set Deck2 = Rest
else if(Deck1.Length > Deck2.Length, Select := Deck1[Deck1.Length-1], Rest := Deck1.Slice[0,Deck1.Length-1]):
set Deck.VirtualDeck += array{Select}
set Deck1 = Rest
else if(Select := Deck2[0], Rest := Deck2.Slice[1]):
set Deck.VirtualDeck += array{Select}
set Deck2 = Rest
Card3 := Deck.LoadNextCard(Self)
Card4 := Deck.LoadNextCard(Self)
if(C3 := Card3?):
C3.SetPosition(Deck.DeckPosition+vector3{X:=1.0})
set TopCard = Card3
if(C4:=Card4?):
C4.SetPosition(Deck.DeckPosition)
set NextCard = Card4
BaseZone := class(BlankZone):
GetNextZone<override>(BaseTree:Tree,X:float, Y:float):?BlankZone:=
return BaseTree.GetZone(X,Y)
CardType := enum:
Diamond
Heart
Spade
Club
#CardSuitToMaterial(Suit:CardType, Value:int):void:=
SuitValueToMaterial(Suit:CardType,Value:int):material:=
case(Suit):
CardType.Diamond => case(Value):
1 => return MaterialsCard.AceDiamond_Mat
2 => return MaterialsCard._2Diamond_Mat
3 => return MaterialsCard._3Diamond_Mat
4 => return MaterialsCard._4Diamond_Mat
5 => return MaterialsCard._5Diamond_Mat
6 => return MaterialsCard._6Diamond_Mat
7 => return MaterialsCard._7Diamond_Mat
8 => return MaterialsCard._8Diamond_Mat
9 => return MaterialsCard._9Diamond_Mat
10 => return MaterialsCard._10Diamond_Mat
11 => return MaterialsCard.JDiamond_Mat
12 => return MaterialsCard.QDiamond_Mat
13 => return MaterialsCard.KDiamond_Mat
_ => return MaterialsCard.CardBack_Mat
CardType.Heart => case(Value):
1 => return MaterialsCard.AceHeart_Mat
2 => return MaterialsCard._2Heart_Mat
3 => return MaterialsCard._3Heart_Mat
4 => return MaterialsCard._4Heart_Mat
5 => return MaterialsCard._5Heart_Mat
6 => return MaterialsCard._6Heart_Mat
7 => return MaterialsCard._7Heart_Mat
8 => return MaterialsCard._8Heart_Mat
9 => return MaterialsCard._9Heart_Mat
10 => return MaterialsCard._10Heart_Mat
11 => return MaterialsCard.JHeart_Mat
12 => return MaterialsCard.QHeart_Mat
13 => return MaterialsCard.KHeart_Mat
_ => return MaterialsCard.CardBack_Mat
CardType.Spade => case(Value):
1 => return MaterialsCard.AceSpade_Mat
2 => return MaterialsCard._2Spade_Mat
3 => return MaterialsCard._3Spade_Mat
4 => return MaterialsCard._4Spade_Mat
5 => return MaterialsCard._5Spade_Mat
6 => return MaterialsCard._6Spade_Mat
7 => return MaterialsCard._7Spade_Mat
8 => return MaterialsCard._8Spade_Mat
9 => return MaterialsCard._9Spade_Mat
10 => return MaterialsCard._10Spade_Mat
11 => return MaterialsCard.JSpade_Mat
12 => return MaterialsCard.QSpade_Mat
13 => return MaterialsCard.KSpade_Mat
_ => return MaterialsCard.CardBack_Mat
CardType.Club => case(Value):
1 => return MaterialsCard.AceClub_Mat
2 => return MaterialsCard._2Club_Mat
3 => return MaterialsCard._3Club_Mat
4 => return MaterialsCard._4Club_Mat
5 => return MaterialsCard._5Club_Mat
6 => return MaterialsCard._6Club_Mat
7 => return MaterialsCard._7Club_Mat
8 => return MaterialsCard._8Club_Mat
9 => return MaterialsCard._9Club_Mat
10 => return MaterialsCard._10Club_Mat
11 => return MaterialsCard.JClub_Mat
12 => return MaterialsCard.QClub_Mat
13 => return MaterialsCard.KClub_Mat
_ => return MaterialsCard.CardBack_Mat
Grab_Obj := interface():
SetPosition(Pos:vector3):void
SetHome(NewHome:BlankZone):void
ReturnHome():void
Focusable := interface():
GetFocalTransform()<transacts>:transform
Card_Deck := class():
FlipAudio:audio_player_device
PlaceAudio:audio_player_device
CardAsset:creative_prop_asset
DeckPosition:vector3
var VirtualDeck:[]Virtual_Card := array{}
GetCardCount()<transacts>:int:=return VirtualDeck.Length
AddVirtualCards(Cards:[]Virtual_Card):void:=
set VirtualDeck += Cards
AddPhysicalCards(Cards:[]Physical_Card):void:=
set VirtualDeck += for(Card:Cards){Card.Virtualise()}
LoadNextCard(SpawnZone:BlankZone):?Physical_Card:=
if(NextCard := VirtualDeck[0], Rest := VirtualDeck.Slice[1]):
set VirtualDeck = Rest
return NextCard.Physicalise(DeckPosition, SpawnZone, CardAsset, FlipAudio, PlaceAudio)
return false
Virtual_Card := class<unique>():
Suit:CardType
Value:int
Physicalise(Position:vector3, Home:BlankZone,CardAsset:creative_prop_asset, FlipAudio:audio_player_device, PlaceAudio:audio_player_device):?Physical_Card :=
isSpawned := SpawnProp(CardAsset, Position, MakeRotationFromYawPitchRollDegrees(180.0, 0.0, 0.0))
if(Spawned := isSpawned(0)?):
Spawned.SetMaterial(SuitValueToMaterial(Suit,Value))
return option{Physical_Card{CardProp := Spawned,Suit := Suit, Value := Value, HomeZone := Home, FlipAudio := FlipAudio, PlaceAudio := PlaceAudio}}
else{return false}
Physical_Card := class(Virtual_Card, Grab_Obj):
CardProp:creative_prop
FlipAudio:audio_player_device
PlaceAudio:audio_player_device
var FaceUp:logic := false
var Rotation:rotation := MakeRotationFromYawPitchRollDegrees(180.0, 0.0, 0.0)
var HomeZone:BlankZone
var Visualising:logic := false
Virtualise():Virtual_Card:=
CardProp.Dispose()
return Virtual_Card{Suit := Suit, Value := Value}
IndicateEffect()<suspends>:void:=
if(Visualising = false):
set Visualising = true
Pos := CardProp.GetTransform().Translation
CardProp.MoveTo(transform{Translation:=Pos, Rotation := Rotation, Scale := vector3{X:=1.0,Y:=0.75,Z:=0.75}}, 0.1)
CardProp.MoveTo(transform{Translation:=Pos, Rotation := Rotation, Scale := vector3{X:=1.0,Y:=0.5,Z:=0.5}}, 0.2)
set Visualising = false
MoveToRightUp(Pos:vector3)<suspends>:void:=
if(FaceUp = false):
CardProp.MoveTo(transform{Translation:=Pos-vector3{X:=207.0}, Rotation := MakeRotationFromYawPitchRollDegrees(90.0, 0.0, 0.0), Scale := vector3{X:=1.0,Y:=1.0,Z:=1.0}}, 0.5)
set Rotation = IdentityRotation()
FlipAudio.Play()
CardProp.MoveTo(transform{Translation:=Pos, Rotation := Rotation, Scale := vector3{X:=1.0,Y:=1.0,Z:=1.0}}, 0.25)
set FaceUp = true
else:
PlaceAudio.Play()
CardProp.MoveTo(Pos,Rotation, 0.75)
MoveToRightUp(Pos:vector3,Scale:vector3)<suspends>:void:=
if(FaceUp = false):
CardProp.MoveTo(transform{Translation:=Pos-vector3{X:=207.0}, Rotation := MakeRotationFromYawPitchRollDegrees(90.0, 0.0, 0.0), Scale := Scale}, 0.5)
set Rotation = IdentityRotation()
FlipAudio.Play()
CardProp.MoveTo(transform{Translation:=Pos,Rotation := Rotation,Scale := Scale}, 0.25)
set FaceUp = true
else:
PlaceAudio.Play()
CardProp.MoveTo(transform{Translation:=Pos,Rotation := Rotation,Scale := Scale}, 0.75)
MoveToBackUp(Pos:vector3)<suspends>:void:=
if(FaceUp = true):
CardProp.MoveTo(Pos-vector3{X:=207.0},MakeRotationFromYawPitchRollDegrees(90.0, 0.0, 0.0), 0.5)
set Rotation = MakeRotationFromYawPitchRollDegrees(180.0, 0.0, 0.0)
FlipAudio.Play()
CardProp.MoveTo(Pos,Rotation, 0.25)
set FaceUp = false
else:
PlaceAudio.Play()
CardProp.MoveTo(Pos,Rotation, 0.75)
MoveToBackUp(Pos:vector3, Time:float)<suspends>:void:=
CardProp.MoveTo(Pos,Rotation, Time)
if(FaceUp = true):
HalfTime := Time*0.5
CardProp.MoveTo(Pos-vector3{X:=207.0},MakeRotationFromYawPitchRollDegrees(90.0, 0.0, 0.0), HalfTime)
set Rotation = MakeRotationFromYawPitchRollDegrees(180.0, 0.0, 0.0)
FlipAudio.Play()
CardProp.MoveTo(Pos,Rotation, HalfTime)
set FaceUp = false
else:
PlaceAudio.Play()
CardProp.MoveTo(Pos,Rotation, Time)
SetPosition<override>(Pos:vector3):void:=if(CardProp.TeleportTo[Pos,Rotation]){}
ReturnHome<override>():void:=
HomeZone.DropHoldable(Self)
SetHome<override>(NewHome:BlankZone):void:=
HomeZone.RemoveHomeLink(Self)
set HomeZone = NewHome
Node := class(Tree):
X:float
Y:float
PP:Tree
PN:Tree
NP:Tree
NN:Tree
GetZone<override>(InX:float,InY:float):?BlankZone:=
if(InX>=X):
if(InY>=Y):
return PP.GetZone(InX, InY)
else:
return PN.GetZone(InX, InY)
else:
if(InY>=Y):
return NP.GetZone(InX, InY)
else:
return NN.GetZone(InX, InY)
CursorState := enum:
Passive
Active
CursorStyle := enum:
Standard
Pointing
Holding
Denial
StyleToMaterial(Style:CursorStyle):material:=
case(Style):
CursorStyle.Standard => return MaterialsCursor.StandardCursor
CursorStyle.Pointing => return MaterialsCursor.PointingCursor
CursorStyle.Holding => return MaterialsCursor.HoldingCursor
CursorStyle.Denial => return MaterialsCursor.DenialCursor
DualController := class():
var ZoneTree:Node
var CursorRef:?CursorHandler := false
var SelectorRef:?SelectorHandler := false
var CursorDepth:float := 980.0
var CursorInUse:logic := false
var Interacting:logic := false
var LastCursorPos:vector2 := vector2{}
UpdateCharAngles(RotYaw:float,RotPitch:float):void:=
if(Cursor := CursorRef?):
if(CursorInUse = false):
NewPos := vector2{X:=RotYaw, Y:=RotPitch}
if(Distance(LastCursorPos,NewPos)>=2.0):
SetState(true)
Cursor.UpdateCursor(ZoneTree, RotYaw, RotPitch)
set LastCursorPos = NewPos
else:
Cursor.UpdateCursor(ZoneTree, RotYaw, RotPitch)
SetState(State:logic):logic:=
if(not CursorRef?.isHolding?;Selector := SelectorRef?; Cursor := CursorRef?):
set CursorInUse = State
if(State = true){Cursor.CursorProp.Show();Cursor.CurrentZone.CursorEnteredFocus(Cursor);Selector.BaseProp.Hide()}else{Cursor.CursorProp.Hide();Cursor.CurrentZone.CursorLeftFocus(Cursor);Selector.BaseProp.Show()}
return true
return false
PressInteract(Agent:agent):void:=
if(Cursor := CursorRef?, Selector := SelectorRef?, FortChar := Agent.GetFortCharacter[]):
if(CursorInUse = true, Rot := FortChar.GetViewRotation().GetYawPitchRollDegrees(),RotYaw := Rot[0], RotPitch := Rot[1]):
Cursor.CursorClick(ZoneTree,RotYaw,RotPitch)
else if(Selector.InteractionDelayed = false and Selector.Lock = false):
spawn{Selector.InteractionDelay()}
Selector.SelectedZone.SelectorInteraction()
ReleaseInteract(Agent:agent, Time:float):void:=
if(Cursor := CursorRef?, FortChar := Agent.GetFortCharacter[]):
if(CursorInUse = true, Rot := FortChar.GetViewRotation().GetYawPitchRollDegrees(),RotYaw := Rot[0], RotPitch := Rot[1]):
Cursor.CursorRelease(ZoneTree,RotYaw,RotPitch)
SelectorHandler := class():
BaseProp:creative_prop
BackRef:DualController
var SelectedZone:BlankZone
var InteractionDelayed:logic := false
var Lock:logic := false
InteractionDelay()<suspends>:void:=
set InteractionDelayed = true
Sleep(1.0)
set InteractionDelayed = false
SetFocus(Obj:Focusable):void:=
if(Zone:=BlankZone[Obj],BaseProp.TeleportTo[Obj.GetFocalTransform()]){set SelectedZone = Zone}
SelectorUp(Agent:agent):void:=
if(BackRef.CursorInUse = true):
NewState := BackRef.SetState(false)
if(NewState=true):
SelectedZone.SelectorUp()
else:
SelectedZone.SelectorUp()
SelectorDown(Agent:agent):void:=
if(BackRef.CursorInUse = true):
NewState := BackRef.SetState(false)
if(NewState=true):
SelectedZone.SelectorDown()
else:
SelectedZone.SelectorDown()
SelectorLeft(Agent:agent):void:=
if(BackRef.CursorInUse = true):
NewState := BackRef.SetState(false)
if(NewState=true):
SelectedZone.SelectorLeft()
else:
SelectedZone.SelectorLeft()
SelectorRight(Agent:agent):void:=
if(BackRef.CursorInUse = true):
NewState := BackRef.SetState(false)
if(NewState=true):
SelectedZone.SelectorRight()
else:
SelectedZone.SelectorRight()
CursorHandler := class():
BackRef:DualController
CursorProp:creative_prop
var isHolding:?tuple(Grab_Obj,vector3) := false
var CurrentZone:BlankZone := BlankZone{XMin := 0.0, XMax := 0.0, YMin := 0.0, YMax := 0.0}
var State:CursorState := CursorState.Passive
var Style:CursorStyle := CursorStyle.Standard
CursorHold(Holdable:?tuple(Grab_Obj,vector3)):void:=if(not isHolding?){BackRef.SetState(true);set isHolding = Holdable; UpdateStyle(CursorStyle.Holding);set State = CursorState.Active; UpdateStyle(CursorStyle.Standard)}
CursorClick(SelectedTree:Tree, X:float, Y:float):void:=
UpdateCursor(SelectedTree, X, Y)
CurrentZone.CursorClick(Self, X, Y)
CursorRelease(SelectedTree:Tree, X:float, Y:float):void:=
if(Holding := isHolding?):
set isHolding = false
UpdateCursor(SelectedTree, X, Y)
CurrentZone.DropHoldable(Holding(0), X, Y)
set State = CursorState.Passive
UpdateStyle(Style)
CurrentZone.CursorRelease(Self, X, Y)
UpdateStyle(DesiredStyle:CursorStyle):void:=
if(State = CursorState.Passive):
CursorProp.SetMaterial(StyleToMaterial(DesiredStyle))
set Style = DesiredStyle
else:
set Style = DesiredStyle
UpdateCursor(SelectedTree:Tree, X:float, Y:float):void:=
if(BackRef.CursorDepth >0.0):
Position := PolarToCartesianWorld(-X,Y, BackRef.CursorDepth)
if(CursorProp.TeleportTo[Position, MakeRotationFromYawPitchRollDegrees(180.0,0.0,0.0)]):
if(Holding := isHolding?){Holding(0).SetPosition(Position+Holding(1))}
isNewZone := SelectedTree.GetZone(X,Y)
if(NewZone := isNewZone?, NewZone <> CurrentZone):
CurrentZone.CursorLeftFocus(Self)
NewZone.CursorEnteredFocus(Self)
set CurrentZone = NewZone
else:
Position := PolarToCartesianWorld(X,Y, BackRef.CursorDepth)
if(CursorProp.TeleportTo[Position, IdentityRotation()]):
if(Holding := isHolding?){Holding(0).SetPosition(Position+Holding(1))}
isNewZone := SelectedTree.GetZone(X,Y)
if(NewZone := isNewZone?, NewZone <> CurrentZone):
CurrentZone.CursorLeftFocus(Self)
NewZone.CursorEnteredFocus(Self)
set CurrentZone = NewZone
CCGDemoController := class(creative_device):
@editable
FlipAudio:audio_player_device := audio_player_device{}
@editable
PlaceAudio:audio_player_device := audio_player_device{}
@editable
CardProp:creative_prop_asset := DefaultCreativePropAsset
@editable
CursorClickTrigger:input_trigger_device := input_trigger_device{}
@editable
CameraSwivle:creative_prop := creative_prop{}
@editable
CursorProp:creative_prop := creative_prop{}
@editable
SelectorProp:creative_prop := creative_prop{}
@editable
HandBaseProp:creative_prop := creative_prop{}
@editable
PlayBaseProp:creative_prop := creative_prop{}
@editable
PlayerRef:player_reference_device := player_reference_device{}
@editable
GameButton:creative_prop := creative_prop{}
@editable
InfoButton:creative_prop := creative_prop{}
@editable
SelectorInteractTrigger:input_trigger_device := input_trigger_device{}
@editable
TriggerUp:input_trigger_device := input_trigger_device{}
@editable
TriggerDown:input_trigger_device := input_trigger_device{}
@editable
TriggerLeft:input_trigger_device := input_trigger_device{}
@editable
TriggerRight:input_trigger_device := input_trigger_device{}
@editable
SkipText:billboard_device := billboard_device{}
@editable
Pickup1Text:billboard_device := billboard_device{}
@editable
Pickup2Text:billboard_device := billboard_device{}
@editable
Pickup3Text:billboard_device := billboard_device{}
@editable
Pickup4Text:billboard_device := billboard_device{}
@editable
Pickup5Text:billboard_device := billboard_device{}
@editable
Rule2Text:billboard_device := billboard_device{}
@editable
Rule7Text:billboard_device := billboard_device{}
@editable
Rule8Text:billboard_device := billboard_device{}
@editable
Rule11Text:billboard_device := billboard_device{}
@editable
Rule13Text:billboard_device := billboard_device{}
@editable
Player1Text:billboard_device := billboard_device{}
@editable
Player2Text:billboard_device := billboard_device{}
@editable
Player3Text:billboard_device := billboard_device{}
@editable
Player4Text:billboard_device := billboard_device{}
@editable
LastWinText:billboard_device := billboard_device{}
@editable
LastLoseText:billboard_device := billboard_device{}
@editable
WinMessage:hud_message_device := hud_message_device{}
@editable
LoseMessage:hud_message_device := hud_message_device{}
@editable
Portal1:matchmaking_portal_device := matchmaking_portal_device{}
@editable
Portal1Frame:creative_prop := creative_prop{}
@editable
Portal2:matchmaking_portal_device := matchmaking_portal_device{}
@editable
Portal2Frame:creative_prop := creative_prop{}
@editable
ShowInteract:input_trigger_device := input_trigger_device{}
@editable
HideInteract:input_trigger_device := input_trigger_device{}
UpdateSelected:event(?Physical_Card) := event(?Physical_Card){}
var GameTree:Node := Node{X:=0.0, Y:=39.166666666, PP := BlankZone{XMin := 0.0, XMax := 0.0, YMin := 0.0, YMax := 0.0}, PN := BlankZone{XMin := 0.0, XMax := 0.0, YMin := 0.0, YMax := 0.0} , NP := BlankZone{XMin := 0.0, XMax := 0.0, YMin := 0.0, YMax := 0.0}, NN := BlankZone{XMin := 0.0, XMax := 0.0, YMin := 0.0, YMax := 0.0}}
var InfoTree:Node := Node{X:=0.0, Y:=39.166666666, PP := BlankZone{XMin := 0.0, XMax := 0.0, YMin := 0.0, YMax := 0.0}, PN := BlankZone{XMin := 0.0, XMax := 0.0, YMin := 0.0, YMax := 0.0} , NP := BlankZone{XMin := 0.0, XMax := 0.0, YMin := 0.0, YMax := 0.0}, NN := BlankZone{XMin := 0.0, XMax := 0.0, YMin := 0.0, YMax := 0.0}}
var ToggleButtonArea:BlankZone := BlankZone{XMin := 0.0, XMax := 0.0, YMin := 0.0, YMax := 0.0}
var HandArea:BlankZone := BlankZone{XMin := 0.0, XMax := 0.0, YMin := 0.0, YMax := 0.0}
var DeckArea:BlankZone := BlankZone{XMin := 0.0, XMax := 0.0, YMin := 0.0, YMax := 0.0}
var PlayArea:BlankZone := BlankZone{XMin := 0.0, XMax := 0.0, YMin := 0.0, YMax := 0.0}
var LevelArea1:BlankZone := BlankZone{XMin := 0.0, XMax := 0.0, YMin := 0.0, YMax := 0.0}
var LevelArea2:BlankZone := BlankZone{XMin := 0.0, XMax := 0.0, YMin := 0.0, YMax := 0.0}
var GameToggle:BlankZone := BlankZone{XMin := 0.0, XMax := 0.0, YMin := 0.0, YMax := 0.0}
var InfoToggle:BlankZone := BlankZone{XMin := 0.0, XMax := 0.0, YMin := 0.0, YMax := 0.0}
var GameSession:Game := EmptyGame{}
var RefPlayer:?player := false
var Controller:DualController := DualController{
ZoneTree:=Node{X:=0.0, Y:=39.166666666, PP := BlankZone{XMin := 0.0, XMax := 0.0, YMin := 0.0, YMax := 0.0}, PN := BlankZone{XMin := 0.0, XMax := 0.0, YMin := 0.0, YMax := 0.0} , NP := BlankZone{XMin := 0.0, XMax := 0.0, YMin := 0.0, YMax := 0.0}, NN := BlankZone{XMin := 0.0, XMax := 0.0, YMin := 0.0, YMax := 0.0}}
}
NoZone:BaseZone := BaseZone{
XMin:= -180.0
XMax := 180.0
YMin := -90.0
YMax :=90.0
}
OnBegin<override>()<suspends>:void=
CursorProp.Hide()
Portal1.Disable()
Portal2.Disable()
SkipText.HideText()
Pickup1Text.HideText()
Pickup2Text.HideText()
Pickup3Text.HideText()
Pickup4Text.HideText()
Pickup5Text.HideText()
Rule2Text.HideText()
Rule7Text.HideText()
Rule8Text.HideText()
Rule11Text.HideText()
Rule13Text.HideText()
Player1Text.HideText()
Player2Text.HideText()
Player3Text.HideText()
Player4Text.HideText()
LastWinText.HideText()
LastLoseText.HideText()
var CardsList:[]Virtual_Card := array{}
for(Suit:array{CardType.Diamond,CardType.Heart,CardType.Spade,CardType.Club}){set CardsList += for(Index:=1..13){Virtual_Card{Suit:=Suit, Value := Index}}}
CardDeck := Card_Deck{CardAsset := CardProp, FlipAudio := FlipAudio, PlaceAudio := PlaceAudio, DeckPosition := vector3{X:= -964.0,Y:=0.0, Z:=1172.0 },VirtualDeck := CardsList}
set PlayArea = PlayZone{
BackRef := Self
BaseProp := PlayBaseProp
XMin := 17.632653-126.5625
XMax := 17.632653-48.0
YMin := -24.75
YMax := 52.6666666666667
}
set HandArea = HandZone{
BackRef := Self
BaseProp := HandBaseProp
XMin := -180.0
XMax := 132.0
YMin := -90.0
YMax :=-39.166666666
}
Level1 := LevelZone{
Frame := Portal1Frame
PortalLink := Portal1
PictureMat :=Materials.SquareKoM_Mat
VideoMat := Materials.KoMFlipBook
Pos := vector3{X:= 961.0,Y := 720.0,Z :=754.0}
BackRef := Self
XMin := 90.0
XMax := 180.0
YMin := -90.0
YMax := -39.166666666
}
Level2 := LevelZone{
Frame := Portal2Frame
PortalLink := Portal2
PictureMat :=Materials.SquareMainImage_Mat
VideoMat := Materials.SHGGFlipBook
Pos := vector3{X:= 961.0,Y := 240.0,Z :=754.0}
BackRef := Self
XMin := 0.0
XMax := 90.0
YMin := -90.0
YMax := -39.166666666
}
NewDeckZone :=DeckZone{
BackRef := Self
TopCard := false
NextCard := false
Deck :=CardDeck
XMin := -19.40625
XMax := 19.40625
YMin := 0.0
YMax :=49.5
}
set LevelArea1 = Level1
set LevelArea2 = Level2
set GameToggle = GameToggleButtonZone{
LeftLink := NewDeckZone
ButtonPos := vector3{X:= -960.0,Y := -768.0,Z :=928.0}
BackRef := Self
BaseProp := GameButton
XMin := -180.0
XMax := -108.929847
YMin := -39.166666666
YMax :=8.33333333333-39.166666666
}
ITog := InfoToggleButtonZone{
ButtonPos := vector3{X:= 964.0,Y := -696.0,Z :=840.0}
LeftLink := LevelArea2
BackRef := Self
BaseProp := InfoButton
XMin := 90.0
XMax := 180.0
YMin := -39.166666666
YMax := -22.33333333333
}
set Level2.LeftLink = ITog
set Level2.RightLink = LevelArea1
set Level1.LeftLink = LevelArea2
set InfoToggle = ITog
FirstCard := CardDeck.LoadNextCard(NewDeckZone)
set NewDeckZone.TopCard = FirstCard
SecondCard := CardDeck.LoadNextCard(NewDeckZone)
set NewDeckZone.NextCard = SecondCard
set DeckArea = NewDeckZone
set GameTree = Node{X:=-19.40625,Y:=-39.166666666,PP := Node{X:=-19.40625,Y:=0.0,PP := Node{X:=19.40625, Y:=49.5, PP := NoZone, PN := NoZone, NP := NoZone, NN := DeckArea},PN := NoZone,NP := NoZone,NN := NoZone},PN := Node{X:=132.0, Y:=-39.166666666, PP := NoZone, PN := NoZone, NP := HandArea, NN := HandArea},NP := Node{X:=17.632653-48.0,Y:=-24.75,PP := NoZone,PN := NoZone,NP := Node{X:=17.632653-126.5625, Y:=52.6666666666667, PP := NoZone, PN := PlayArea, NP := NoZone, NN := Node{X:=-108.929847, Y:=(8.33333333333*2.0)-24.75, PP := NoZone, PN := GameToggle, NP := NoZone, NN := GameToggle}},NN := NoZone},NN := Node{X:=-180.0, Y:=-39.166666666, PP := HandArea, PN := HandArea, NP := NoZone, NN := NoZone}}
set InfoTree = Node{X:=90.0, Y:=-22.33333333333, PP := NoZone, PN := Node{X:=180.0,Y:=-39.166666666, PP := InfoToggle, PN := NoZone, NP := InfoToggle, NN := NoZone} , NP := NoZone, NN := Node{X:=0.0, Y:=-67.5, PP := NoZone, PN := NoZone, NP := Node{X:=-90.0, Y:=67.5, PP := Level2, PN := Level2, NP := Level1, NN := Level1}, NN := NoZone}}
NewController := DualController{ZoneTree:=InfoTree}
Selector := SelectorHandler{BackRef := NewController, BaseProp := SelectorProp, SelectedZone := DeckArea}
set Controller = NewController
set Controller.CursorRef = option{CursorHandler{BackRef := NewController, CursorProp := CursorProp}}
set Controller.SelectorRef = option{Selector}
Selector.SetFocus(ITog)
loop:
Agent := PlayerRef.GetAgent()
if(Char := Agent?.GetFortCharacter[], Deck := DeckZone[DeckArea], Play := PlayZone[PlayArea], Hand := HandZone[HandArea]):
if(PRef := player[Agent?]){set RefPlayer = option{PRef}}
set GameSession = SolitairSwitch{
BackRef := Self
SkipText:=SkipText
Pickup1Text:=Pickup1Text
Pickup2Text:=Pickup2Text
Pickup3Text:=Pickup3Text
Pickup4Text:=Pickup4Text
Pickup5Text:=Pickup5Text
Rule2Text:=Rule2Text
Rule7Text:=Rule7Text
Rule8Text:=Rule8Text
Rule11Text:=Rule11Text
Rule13Text:=Rule13Text
LastWinText := LastWinText
LastLoseText := LastLoseText
PlayerText := array{Player1Text,Player2Text,Player3Text,Player4Text}
DeckArea := Deck
PlayArea := Play
HandAreas := array{Hand,AIHandZone{BackRef := Self,XMin := 181.75, YMin := 928.0},AIHandZone{BackRef := Self,XMin := 181.75, YMin := 1120.0},AIHandZone{BackRef := Self, XMin := 181.75, YMin := 1312.0}}
CurrentPlayer := (0,Hand)
}
CursorClickTrigger.PressedEvent.Subscribe(Controller.PressInteract)
CursorClickTrigger.ReleasedEvent.Subscribe(Controller.ReleaseInteract)
SelectorInteractTrigger.PressedEvent.Subscribe(Controller.PressInteract)
TriggerUp.PressedEvent.Subscribe(Selector.SelectorUp)
TriggerDown.PressedEvent.Subscribe(Selector.SelectorDown)
TriggerLeft.PressedEvent.Subscribe(Selector.SelectorLeft)
TriggerRight.PressedEvent.Subscribe(Selector.SelectorRight)
race:
GameSession.HandleGame()
loop:
Rot := Char.GetViewRotation().GetYawPitchRollDegrees()
if(RotYaw := Rot[0], RotPitch := Rot[1]){Controller.UpdateCharAngles(RotYaw,RotPitch)}
Sleep(0.0)
Sleep(0.0)
var InfoShowing:?logic := option{true}
ToggleInfoState():void:=
if(Showing := InfoShowing?):
if(Showing = true):
if(Focus := Focusable[DeckArea], Sel := Controller.SelectorRef?){Sel.SetFocus(Focus)}
set Controller.CursorDepth = -980.0
set InfoShowing = false
set Controller.ZoneTree = GameTree
spawn{SwivleCamera(false)}
else:
if(Focus := Focusable[InfoToggle], Sel := Controller.SelectorRef?){Sel.SetFocus(Focus)}
set Controller.CursorDepth = 980.0
set InfoShowing = false
set Controller.ZoneTree = InfoTree
spawn{SwivleCamera(true)}
SwivleCamera(State:logic)<suspends>:void:=
if(SGame := SolitairSwitch[GameSession]):
if(State = false):
CameraSwivle.MoveTo(vector3{}, MakeRotationFromYawPitchRollDegrees(0.0,0.0,0.0),1.0)
set SGame.Paused = false
set InfoShowing = option{false}
else:
set SGame.Paused = true
CameraSwivle.MoveTo(vector3{}, MakeRotationFromYawPitchRollDegrees(180.0,0.0,0.0),1.0)
set InfoShowing = option{true}
Visualise(Visualiser:TurnVitualiser)<suspends>:?Virtual_Card:=
var Current:?Physical_Card := false
loop:
set Current = race:
UpdateSelected.Await()
block:
if(Array := Visualiser.SimulatedCards[Virtual_Card[Current?]]):
VisLoop(Array)
else:
UpdateSelected.Await()
return false
VisLoop(Array:[]Virtual_Card)<suspends>:?Physical_Card :=
loop:
for(VirtCard:Array;Card := Physical_Card[VirtCard]):
spawn{Card.IndicateEffect()}
Sleep(0.5)
Sleep(0.25)
return false
GameState := enum:
StandardTurn
Play2orPickup2
Play7andDiamond
Play7andHeart
Play7andSpade
Play7andClub
Play8orSkip
PlayKingorPickup5
ToString(State:GameState):string:=
case(State):
GameState.StandardTurn => return "StandardTurn"
GameState.Play2orPickup2 => return "Play2orPickup2"
GameState.Play7andDiamond => return "Play7andDiamond"
GameState.Play7andHeart => return "Play7andHeart"
GameState.Play7andSpade => return "Play7andSpade"
GameState.Play7andClub => return "Play7andClub"
GameState.Play8orSkip => return "Play8orSkip"
GameState.PlayKingorPickup5 => return "PlayKingorPickup5"
BoolToString(Val:logic):string:=
if(Val=true){return "True"}else{return "False"}
Game:=interface:
var GamePaused:logic:=false
OutOfCards():void
DealCards(Count:int)<suspends>:void
HandleGame()<suspends>:void
CanPlay(Array:[]Virtual_Card):logic
ApplyTurn(Player:BlankZone,isCard:?Virtual_Card):logic
EmptyGame := class(Game):
OutOfCards<override>():void:=return
DealCards<override>(Count:int)<suspends>:void:=return
HandleGame<override>()<suspends>:void:=return
ApplyTurn<override>(Player:BlankZone,isCard:?Virtual_Card):logic:=return false
CanPlay<override>(Array:[]Virtual_Card):logic:=return false
SolitairSwitch := class(EmptyGame):
BackRef:CCGDemoController
ChooseCard:event(?Virtual_Card):=event(?Virtual_Card){}
DeckArea:DeckZone
PlayArea:PlayZone
HandAreas:[]HandZone
EndGame:event(logic):=event(logic){}
var CurrentPlayer:tuple(int, HandZone)
var LastPlayedCard:?Virtual_Card := false
var State:GameState := GameState.StandardTurn
var Reversed:logic := false
var Paused:logic := true
var GameString:string := ""
SkipText:billboard_device
Pickup1Text:billboard_device
Pickup2Text:billboard_device
Pickup3Text:billboard_device
Pickup4Text:billboard_device
Pickup5Text:billboard_device
Rule2Text:billboard_device
Rule7Text:billboard_device
Rule8Text:billboard_device
Rule11Text:billboard_device
Rule13Text:billboard_device
LastWinText:billboard_device
LastLoseText:billboard_device
PlayerText:[]billboard_device
OutOfCards<override>():void:=
if(TopCard := PlayArea.PhysicalStack[PlayArea.PhysicalStack.Length-1], Rest := PlayArea.PhysicalStack.Slice[0,PlayArea.PhysicalStack.Length-1]):
DeckArea.Deck.AddVirtualCards(PlayArea.VirtualStack+for(RCard:Rest){RCard.Virtualise()})
set PlayArea.PhysicalStack = array{TopCard}
set PlayArea.VirtualStack = array{}
DealCards<override>(Count:int)<suspends>:void:=
for(Index:=0..Count-1):
for(HandIndex := 0..3,Hand:=HandAreas[HandIndex], Card := DeckArea.TopCard?):
Hand.DealCard(Card)
Sleep(0.2)
ApplyTurn<override>(Player:BlankZone, isCard:?Virtual_Card):logic:=
if(Physical_Card[isCard?].HomeZone = DeckArea):
ChooseCard.Signal(isCard)
return true
else if(Player = CurrentPlayer(1)):
if(OldCard := LastPlayedCard?, Card := isCard?):
case(State):
GameState.Play2orPickup2 => if(Card.Value <> 2){return false}
GameState.Play7andDiamond => if(Card.Suit <> CardType.Diamond){return false}
GameState.Play7andHeart => if(Card.Suit <> CardType.Heart){return false}
GameState.Play7andSpade => if(Card.Suit <> CardType.Spade){return false}
GameState.Play7andClub => if(Card.Suit <> CardType.Club){return false}
GameState.Play8orSkip => if(Card.Value <> 8){return false}
GameState.PlayKingorPickup5 => if(Card.Value <> 13){return false}
_ => if(Card.Suit <> OldCard.Suit and Card.Value <> OldCard.Value and Card.Value <> 1){return false}
ChooseCard.Signal(isCard)
return true
else:
ChooseCard.Signal(isCard)
return true
else:
return false
NextPlayer():void:=
if(Reversed = false):
if(CurrentPlayer(0)<3, NextPlayerID:=CurrentPlayer(0)+1, Player := HandAreas[NextPlayerID]):
if(OldText := PlayerText[CurrentPlayer(0)], NewText := PlayerText[NextPlayerID]):
OldText.HideText()
NewText.ShowText()
set CurrentPlayer = (NextPlayerID,Player)
else if(Player := HandAreas[0]):
if(OldText := PlayerText[CurrentPlayer(0)], NewText := PlayerText[0]):
OldText.HideText()
NewText.ShowText()
set CurrentPlayer = (0,Player)
else:
if(CurrentPlayer(0)>0, NextPlayerID:=CurrentPlayer(0)-1, Player := HandAreas[NextPlayerID]):
if(OldText := PlayerText[CurrentPlayer(0)], NewText := PlayerText[NextPlayerID]):
OldText.HideText()
NewText.ShowText()
set CurrentPlayer = (NextPlayerID,Player)
else if(Player := HandAreas[3]):
if(OldText := PlayerText[CurrentPlayer(0)], NewText := PlayerText[3]):
OldText.HideText()
NewText.ShowText()
set CurrentPlayer = (3,Player)
Play2orPickup2(isCard:?Virtual_Card)<suspends>:void:=
if(Card := isCard?):
if(PhyCard := Physical_Card[Card]){PlayArea.DropHoldable(PhyCard)}
SetState(GameState.Play2orPickup2)
else:
if(PickupState = -1):
set PickupState = 0
else:
AddCardsToPlayer(2)
SetState(GameState.StandardTurn)
NextPlayer()
Play7andSuit(Suit:CardType, isCard:?Virtual_Card):void:=
if(Card := isCard?, Card.Suit = Suit):
set LastPlayedCard = isCard
if(PhyCard := Physical_Card[Card]){PlayArea.DropHoldable(PhyCard)}
else:
SetState(GameState.StandardTurn)
NextPlayer()
Play8orSkip(isCard:?Virtual_Card):void:=
if(Card := isCard?):
set LastPlayedCard = isCard
if(PhyCard := Physical_Card[Card]){PlayArea.DropHoldable(PhyCard)}
else:
SetState(GameState.StandardTurn)
NextPlayer()
PlayKingorPickup5(isCard:?Virtual_Card)<suspends>:void:=
if(Card := isCard?):
set LastPlayedCard = isCard
if(Card.Suit = CardType.Diamond or Card.Suit = CardType.Heart):
SetState(GameState.StandardTurn)
else:
SetState(GameState.PlayKingorPickup5)
if(PhyCard := Physical_Card[Card]){PlayArea.DropHoldable(PhyCard)}
else:
if(PickupState = -1):
set PickupState = 0
else:
AddCardsToPlayer(5)
SetState(GameState.StandardTurn)
NextPlayer()
StandardPlay(isCard:?Virtual_Card):void:=
if(Card := isCard?):
case(Card.Value):
2 => SetState(GameState.Play2orPickup2)
7 => block:
case(Card.Suit):
CardType.Diamond => SetState(GameState.Play7andDiamond)
CardType.Heart => SetState(GameState.Play7andHeart)
CardType.Spade => SetState(GameState.Play7andSpade)
CardType.Club => SetState(GameState.Play7andClub)
return if(PhyCard := Physical_Card[Card]){PlayArea.DropHoldable(PhyCard)}
8 => SetState(GameState.Play8orSkip)
11 => if(Reversed = true){set Reversed = false; Rule11Text.HideText()}else{set Reversed = true; Rule11Text.ShowText()}
13 => if(Card.Suit = CardType.Spade or Card.Suit = CardType.Club){SetState(GameState.PlayKingorPickup5)}
_ =>
if(PhyCard := Physical_Card[Card]){PlayArea.DropHoldable(PhyCard)}
NextPlayer()
AddCardsToPlayer(Count:int)<suspends>:void:=
for(Index:=0..Count-1;NewCard:=DeckArea.TopCard?;CurrentPlayer(1).HandArray.Length < 8){
CurrentPlayer(1).DropHoldable(NewCard)
Sleep(1.1)
}
CanPlay<override>(Array:[]Virtual_Card):logic:=
if(LastCard := LastPlayedCard?):
for(Card:Array, Card.Suit = LastCard.Suit or Card.Value = LastCard.Value){
return true}
return false
return true
var PickupState:int :=0
GetPickupCountText(Count:int)<transacts>:billboard_device:=
PickCount := Clamp(Clamp(Count,0,8-CurrentPlayer(1).HandArray.Length),0,DeckArea.GetCardCount())
case(PickCount):
5 => block{set PickupState = 5; return Pickup5Text}
4 => block{set PickupState = 4; return Pickup4Text}
3 => block{set PickupState = 3; return Pickup3Text}
2 => block{set PickupState = 2; return Pickup2Text}
1 => block{set PickupState = 1; return Pickup1Text}
_ => block{set PickupState = 0; return billboard_device{}}
RemovePickupCount():void:=
Rule2Text.HideText()
Rule13Text.HideText()
case(PickupState):
5 => Pickup5Text.HideText()
4 => Pickup4Text.HideText()
3 => Pickup3Text.HideText()
2 => Pickup2Text.HideText()
1 => Pickup1Text.HideText()
_ => SkipText.HideText()
set PickupState = 0
DecrementPickupCount():void:=
case(PickupState):
5 => block{Pickup5Text.HideText(),Pickup4Text.ShowText(),set PickupState = 4}
4 => block{Pickup4Text.HideText(),Pickup3Text.ShowText(),set PickupState = 3}
3 => block{Pickup3Text.HideText(),Pickup2Text.ShowText(),set PickupState = 2}
2 => block{Pickup2Text.HideText(),Pickup1Text.ShowText(),set PickupState = 1}
_ => block{Pickup1Text.HideText(),RemovePickupCount();set PickupState = -1;ApplyTurn(CurrentPlayer(1),false)}
ClampedPickup(Val:int, Hand:HandZone)<transacts>:int := Clamp(Clamp(Val,0,8-Hand.HandArray.Length),0,DeckArea.GetCardCount())
SetState(NewState:GameState):void:=
case(State):
GameState.StandardTurn => case(NewState):
GameState.StandardTurn =>
GameState.Play2orPickup2 => block{GetPickupCountText(2).ShowText(),Rule2Text.ShowText()}
GameState.Play7andDiamond => block{Rule7Text.ShowText(),SkipText.ShowText()}
GameState.Play7andHeart => block{Rule7Text.ShowText(),SkipText.ShowText()}
GameState.Play7andSpade => block{Rule7Text.ShowText(),SkipText.ShowText()}
GameState.Play7andClub => block{Rule7Text.ShowText(),SkipText.ShowText()}
GameState.Play8orSkip => block{Rule8Text.ShowText(),SkipText.ShowText()}
GameState.PlayKingorPickup5 => block{GetPickupCountText(5).ShowText(),Rule13Text.ShowText()}
GameState.Play2orPickup2 => case(NewState):
GameState.StandardTurn => RemovePickupCount()
GameState.Play2orPickup2 => block{RemovePickupCount(),GetPickupCountText(2).ShowText(),Rule2Text.ShowText()}
GameState.Play7andDiamond => block{RemovePickupCount(),Rule7Text.ShowText(),SkipText.ShowText()}
GameState.Play7andHeart => block{RemovePickupCount(),Rule7Text.ShowText(),SkipText.ShowText()}
GameState.Play7andSpade => block{RemovePickupCount(),Rule7Text.ShowText(),SkipText.ShowText()}
GameState.Play7andClub => block{RemovePickupCount(),Rule7Text.ShowText(),SkipText.ShowText()}
GameState.Play8orSkip => block{RemovePickupCount(),Rule8Text.ShowText(),SkipText.ShowText()}
GameState.PlayKingorPickup5 => block{RemovePickupCount();GetPickupCountText(5).ShowText(),Rule13Text.ShowText()}
GameState.Play7andDiamond => case(NewState):
GameState.StandardTurn => block{Rule7Text.HideText(),SkipText.HideText()}
GameState.Play2orPickup2 => block{Rule7Text.HideText(),SkipText.HideText(),GetPickupCountText(2).ShowText(),Rule2Text.ShowText()}
GameState.Play7andDiamond =>
GameState.Play7andHeart =>
GameState.Play7andSpade =>
GameState.Play7andClub =>
GameState.Play8orSkip => block{Rule7Text.HideText(),SkipText.HideText(),Rule8Text.ShowText()}
GameState.PlayKingorPickup5 => block{Rule7Text.HideText(),SkipText.HideText(),GetPickupCountText(5).ShowText(),Rule13Text.ShowText()}
GameState.Play7andHeart => case(NewState):
GameState.StandardTurn => block{Rule7Text.HideText(),SkipText.HideText()}
GameState.Play2orPickup2 => block{Rule7Text.HideText(),SkipText.HideText(),GetPickupCountText(2).ShowText(),Rule2Text.ShowText()}
GameState.Play7andDiamond =>
GameState.Play7andHeart =>
GameState.Play7andSpade =>
GameState.Play7andClub =>
GameState.Play8orSkip => block{Rule7Text.HideText(),SkipText.HideText(),Rule8Text.ShowText()}
GameState.PlayKingorPickup5 => block{Rule7Text.HideText(),SkipText.HideText(),GetPickupCountText(5).ShowText(),Rule13Text.ShowText()}
GameState.Play7andSpade => case(NewState):
GameState.StandardTurn => block{Rule7Text.HideText(),SkipText.HideText()}
GameState.Play2orPickup2 => block{Rule7Text.HideText(),SkipText.HideText(),GetPickupCountText(2).ShowText(),Rule2Text.ShowText()}
GameState.Play7andDiamond =>
GameState.Play7andHeart =>
GameState.Play7andSpade =>
GameState.Play7andClub =>
GameState.Play8orSkip => block{Rule7Text.HideText(),SkipText.HideText(),Rule8Text.ShowText()}
GameState.PlayKingorPickup5 => block{Rule7Text.HideText(),SkipText.HideText(),GetPickupCountText(5).ShowText(),Rule13Text.ShowText()}
GameState.Play7andClub => case(NewState):
GameState.StandardTurn => block{Rule7Text.HideText(),SkipText.HideText()}
GameState.Play2orPickup2 => block{Rule7Text.HideText(),SkipText.HideText(),GetPickupCountText(2).ShowText(),Rule2Text.ShowText()}
GameState.Play7andDiamond =>
GameState.Play7andHeart =>
GameState.Play7andSpade =>
GameState.Play7andClub =>
GameState.Play8orSkip => block{Rule7Text.HideText(),SkipText.HideText(),Rule8Text.ShowText()}
GameState.PlayKingorPickup5 => block{Rule7Text.HideText(),SkipText.HideText(),GetPickupCountText(5).ShowText(),Rule13Text.ShowText()}
GameState.Play8orSkip => case(NewState):
GameState.StandardTurn => Rule8Text.HideText()
GameState.Play2orPickup2 => block{Rule8Text.HideText();GetPickupCountText(2).ShowText(),Rule2Text.ShowText()}
GameState.Play7andDiamond => block{Rule8Text.HideText();Rule7Text.ShowText(),SkipText.ShowText()}
GameState.Play7andHeart => block{Rule8Text.HideText();Rule7Text.ShowText(),SkipText.ShowText()}
GameState.Play7andSpade => block{Rule8Text.HideText();Rule7Text.ShowText(),SkipText.ShowText()}
GameState.Play7andClub => block{Rule8Text.HideText();Rule7Text.ShowText(),SkipText.ShowText()}
GameState.Play8orSkip =>
GameState.PlayKingorPickup5 => block{Rule8Text.HideText();GetPickupCountText(5).ShowText(),Rule13Text.ShowText()}
GameState.PlayKingorPickup5 => case(NewState):
GameState.StandardTurn => RemovePickupCount()
GameState.Play2orPickup2 => block{RemovePickupCount(),GetPickupCountText(2).ShowText(),Rule2Text.ShowText()}
GameState.Play7andDiamond => block{RemovePickupCount(),Rule7Text.ShowText(),SkipText.ShowText()}
GameState.Play7andHeart => block{RemovePickupCount(),Rule7Text.ShowText(),SkipText.ShowText()}
GameState.Play7andSpade => block{RemovePickupCount(),Rule7Text.ShowText(),SkipText.ShowText()}
GameState.Play7andClub => block{RemovePickupCount(),Rule7Text.ShowText(),SkipText.ShowText()}
GameState.Play8orSkip => block{RemovePickupCount(),Rule8Text.ShowText(),SkipText.ShowText()}
GameState.PlayKingorPickup5 => block{RemovePickupCount();GetPickupCountText(5).ShowText(),Rule13Text.ShowText()}
set State = NewState
HandleGame<override>()<suspends>:void:=
Visualiser := TurnVitualiser{}
loop:
SkipText.HideText()
Pickup1Text.HideText()
Pickup2Text.HideText()
Pickup3Text.HideText()
Pickup4Text.HideText()
Pickup5Text.HideText()
Rule2Text.HideText()
Rule7Text.HideText()
Rule8Text.HideText()
Rule11Text.HideText()
Rule13Text.HideText()
if(Player1Text := PlayerText[0],Player2Text := PlayerText[1],Player3Text := PlayerText[2],Player4Text := PlayerText[3]):
Player1Text.HideText()
Player2Text.HideText()
Player3Text.HideText()
Player4Text.HideText()
if(Paused = true):
loop:
Sleep(1.0)
if(Paused = false):
break
if(P1:=HandAreas[0]):
set CurrentPlayer = (0,P1)
set Reversed = false
DeckArea.QuickShuffle(7)
DealCards(5)
Sleep(1.5)
if(Card := DeckArea.TopCard?):
PlayArea.DropHoldable(Card)
set LastPlayedCard = option{Card}
var EndCount:int := 0
loop:
if(Paused = true):
loop:
Sleep(1.0)
if(Paused = false):
break
else:
Sleep(1.1)
if(State = GameState.StandardTurn):
AddCardsToPlayer(1)
if(EndCount = 4):
break
else:
if(AI := AIHandZone[CurrentPlayer(1)]):
Sleep(1.0)
NewCard := AI.ChooseNextCard(LastPlayedCard, State)
DeckCount := CurrentPlayer(1).HandArray.Length
case(State):
GameState.Play2orPickup2 => Play2orPickup2(NewCard)
GameState.Play7andDiamond => Play7andSuit(CardType.Diamond,NewCard)
GameState.Play7andHeart => Play7andSuit(CardType.Heart,NewCard)
GameState.Play7andSpade => Play7andSuit(CardType.Spade,NewCard)
GameState.Play7andClub => Play7andSuit(CardType.Club,NewCard)
GameState.Play8orSkip =>Play8orSkip(NewCard)
GameState.PlayKingorPickup5 => PlayKingorPickup5(NewCard)
_ => block{StandardPlay(NewCard),if(not NewCard?, not DeckArea.TopCard? or DeckCount = 8){set EndCount += 1}}
if(NewCard?){set LastPlayedCard = NewCard;set EndCount = 0}
else if(Player := HandZone[CurrentPlayer(1)], Player.HandArray.Length <> 0 or DeckArea.GetCardCount() <> 0):
Sleep(1.0)
if(Con := BackRef.Controller.SelectorRef?){set Con.Lock = false}
if(State <> GameState.Play2orPickup2 and State <> GameState.PlayKingorPickup5){SkipText.ShowText()}
if(AI1:=HandAreas[1],AI2:=HandAreas[2],AI3:=HandAreas[3]):
Visualiser.SimulatePlayerTurns(State, Reversed, LastPlayedCard, Player.HandArray, AI1.HandArray, AI2.HandArray, AI3.HandArray)
NewCard := race:
block{BackRef.UpdateSelected.Signal(Player.SelectedCard);ChooseCard.Await()}
BackRef.Visualise(Visualiser)
DeckCount := CurrentPlayer(1).HandArray.Length
case(State):
GameState.Play2orPickup2 => block{Play2orPickup2(NewCard);Sleep(1.0)}
GameState.Play7andDiamond => Play7andSuit(CardType.Diamond,NewCard)
GameState.Play7andHeart => Play7andSuit(CardType.Heart,NewCard)
GameState.Play7andSpade => Play7andSuit(CardType.Spade,NewCard)
GameState.Play7andClub => Play7andSuit(CardType.Club,NewCard)
GameState.Play8orSkip =>Play8orSkip(NewCard)
GameState.PlayKingorPickup5 => block{PlayKingorPickup5(NewCard);Sleep(1.0)}
_ => block{StandardPlay(NewCard),if(not NewCard?, not DeckArea.TopCard? or DeckCount = 8){set EndCount += 1}}
if(NewCard?){set LastPlayedCard = NewCard;set EndCount = 0}
if(Con := BackRef.Controller.SelectorRef?){set Con.Lock = true}
SkipText.HideText()
Sleep(0.5)
else:
NextPlayer()
var EndOut:logic := true
for(Hand:HandAreas, Hand.HandArray.Length <> 0){set EndOut = false}
if(EndOut = true):
LastWinText.ShowText()
LastLoseText.HideText()
BackRef.WinMessage.Show()
else:
LastLoseText.ShowText()
LastWinText.HideText()
BackRef.LoseMessage.Show()
Sleep(0.5)
PlayArea.ReturnCards()
for(Hand:HandAreas){DeckArea.Deck.AddVirtualCards(Hand.ReturnCards())}
Sleep(0.5)
var CardsList:[]Virtual_Card := array{}
for(Suit:array{CardType.Diamond,CardType.Heart,CardType.Spade,CardType.Club}){set CardsList += for(Index:=1..13){Virtual_Card{Suit:=Suit, Value := Index}}}
DeckArea.SetNewDeck(CardsList)
Sleep(4.0)
TurnVitualiser := class():
var SimulatedCards:[Virtual_Card][]Virtual_Card:=map{}
SimulatePlayerTurns(State:GameState, Reversed:logic, LastCard:?Virtual_Card, PlayerCards:[]Virtual_Card,AI2Cards:[]Virtual_Card,AI3Cards:[]Virtual_Card,AI4Cards:[]Virtual_Card):void:=
set SimulatedCards = map{}
for(CardIndex := 0..PlayerCards.Length-1;PlayerCard:=PlayerCards[CardIndex]; PlayerCard.Value <> 7;PlayerCard.Value = 1 or PlayerCard.Value = LastCard?.Value or PlayerCard.Suit = LastCard?.Suit):
var TempAI2:[]Virtual_Card := AI2Cards
var TempAI3:[]Virtual_Card := AI3Cards
var TempAI4:[]Virtual_Card := AI4Cards
var PlayerIndex:int :=0
var SetState:GameState := State
var SetReversed:logic := Reversed
if(LastCard?.Value <> 7):
case(PlayerCard.Value):
2 => set SetState = GameState.Play2orPickup2
7 => case(PlayerCard.Suit):
CardType.Diamond => set SetState = GameState.Play7andDiamond
CardType.Heart => set SetState = GameState.Play7andHeart
CardType.Spade => set SetState = GameState.Play7andSpade
CardType.Club => set SetState = GameState.Play7andClub
8 => set SetState = GameState.Play8orSkip
11 => if(SetReversed=true){ set SetReversed =false}else{ set SetReversed =true}
13 => set SetState = GameState.PlayKingorPickup5
_ =>
var PreviousCard:?Virtual_Card := option{PlayerCard}
var CardArray:[]Virtual_Card := array{}
loop:
if(PlayerIndex <> 5):
if(SetState <> GameState.Play7andDiamond and SetState <> GameState.Play7andHeart and SetState <> GameState.Play7andSpade and SetState <> GameState.Play7andClub):
set PlayerIndex = NextPlayer(SetReversed,PlayerIndex)
NextCard:?Virtual_Card :=case(PlayerIndex):
1 => SimulateAITurn(TempAI2, PreviousCard, SetState)
2 => SimulateAITurn(TempAI3, PreviousCard, SetState)
3 => SimulateAITurn(TempAI4, PreviousCard, SetState)
_ => false
if(Card := NextCard?):
case(PlayerIndex):
1 => set TempAI2 = for(AICard:TempAI2, Card <> AICard){AICard}
2 => set TempAI3 = for(AICard:TempAI3, Card <> AICard){AICard}
3 => set TempAI4 = for(AICard:TempAI4, Card <> AICard){AICard}
_ =>
set CardArray += array{Card}
set PreviousCard = NextCard
case(Card.Value):
2 => set SetState = GameState.Play2orPickup2
7 => case(PlayerCard.Suit):
CardType.Diamond => set SetState = GameState.Play7andDiamond
CardType.Heart => set SetState = GameState.Play7andHeart
CardType.Spade => set SetState = GameState.Play7andSpade
CardType.Club => set SetState = GameState.Play7andClub
8 => set SetState = GameState.Play8orSkip
11 => set SetReversed = if(SetReversed=true){false}else{true}
13 => set SetState = GameState.PlayKingorPickup5
_ =>
else:
set SetState = GameState.StandardTurn
else{break}
if(set SimulatedCards[PlayerCard]=CardArray){}
SimulateAITurn(CardArray:[]Virtual_Card, isTestCard:?Virtual_Card, Play:GameState):?Virtual_Card:=
if(TestCard:=isTestCard?):
case(Play):
GameState.Play2orPickup2 => block{for(Card:CardArray, Card.Value = 2){return option{Card}};return false}
GameState.Play7andDiamond => block{for(Card:CardArray, Card.Suit = CardType.Diamond){return option{Card}};return false}
GameState.Play7andHeart => block{for(Card:CardArray, Card.Suit = CardType.Heart){return option{Card}};return false}
GameState.Play7andSpade => block{for(Card:CardArray, Card.Suit = CardType.Spade){return option{Card}};return false}
GameState.Play7andClub => block{for(Card:CardArray, Card.Suit = CardType.Club){return option{Card}};return false}
GameState.Play8orSkip => block{for(Card:CardArray, Card.Value = 8){return option{Card}};return false}
GameState.PlayKingorPickup5 => block{for(Card:CardArray, Card.Value = 13){return option{Card}};return false}
_ => return PickStandard(CardArray,TestCard)
else:
return false
PickStandard(CardArray:[]Virtual_Card, TestCard:Virtual_Card):?Virtual_Card:=
for(Card:CardArray, TestCard.Suit = Card.Suit and TestCard.Value = 7){return option{Card}}
for(Card:CardArray, TestCard.Suit = Card.Suit or (TestCard.Value = Card.Value <> 1)){return option{Card}}
var Aces:[]Virtual_Card := array{}
var SuitCounts:[CardType]int := map{CardType.Diamond => 0,CardType.Heart => 0,CardType.Spade => 0,CardType.Club => 0}
for(Card:CardArray){if(Card.Value = 1){set Aces+=array{Card}}else{if(set SuitCounts[Card.Suit]+=1){}}}
if(var LargestCard:Virtual_Card := Aces[0]):
if(Aces.Length>1):
for(Index:=1..Aces.Length, TestAce := Aces[Index], SuitCounts[TestAce.Suit]>SuitCounts[LargestCard.Suit]){set LargestCard = TestAce}
return option{LargestCard}
return false
NextPlayer(Reversed:logic, CurrentIndex:int):int:=
if(Reversed = false):
if(CurrentIndex<3):
return CurrentIndex+1
else:
return 5
else:
if(CurrentIndex>0):
if(CurrentIndex>1):
return CurrentIndex-1
else:
return 5
else:
return 3