Com expressões case, é possível controlar o fluxo de um programa a partir de uma lista de opções. A instrução case no Verse é uma maneira de testar um valor em relação a vários valores possíveis (como se estivesse usando =) e executar códigos conforme a correspondência.
O uso de expressões case pode ser encontrado em todos os tipos de aplicativos, como em jogos em que há um personagem não jogável (PNJ).
Por exemplo, digamos que você usa o dispositivo Gerador de Guardas para gerar um guarda com opção de patrulha habilitada. Após um guarda ser gerado no jogo, ele terá alguns estados ativos possíveis, inclusive Ocioso, Patrulha, Alerta, Ataque e Coleta. Um diagrama de transição de alto nível para isso teria esta aparência:
Você pode observar essas transições de estado no jogo.
Neste vídeo, o guarda tem sua opção de patrulhamento ativada como comportamento padrão.
No vídeo, o guarda passa de patrulhar a base científica para coletar alguns recursos. Em seguida, o guarda avista o jogador, que o coloca em estado de alerta (indicado pelo ponto de interrogação flutuando) antes de entrar no seu estado de ataque (indicado pelo ponto de exclamação flutuando).
Dependendo do estado em que o guarda está, ele exibirá certos comportamentos que geralmente são codificados como funções e são chamadas quando o programa escolher entrar em um estado específico.
Em código, esta transição de estado de guarda de alto nível teria esta aparência:
case(GuardStateVariable):
idle_state =>
RunIdleAnimation()
SearchPlayerCharacter()
harvest_state =>
GatherResources()
alert_state=>
RunAlertAnimation()
PlayAlertSound()
DisplayAlertUIElement()
Essa expressão case passa um rótulo que diz ao programa quais funções executar se o guarda entrar em um estado específico.
Nesta expressão, o patrol_state do guarda é o caso padrão, pois um guarda com patrulha habilitada deve executar seu comportamento padrão.
Sintaticamente, isso é igual a:
expression0
case (test-arg-block):
label1 =>
expression1
label2 =>
expression2
_ =>
expression3 for the default case
expression4Cada padrão no bloco case, como label1 e label2, deve usar a forma constante => bloco, em que a constante pode ser do tipo integer, logic, string, char ou enum. Por isso, instruções case funcionam apenas com int, logic, string, char e enums.
Estrutura
Estruturalmente, a expressão de caso do Verse executa códigos baseados na entrada do bloco de argumentos de teste GuardStateVariable e funciona praticamente da mesma forma que uma série de expressões if.
Neste exemplo, o programa Verse executa expression3 se GuardStateVariable resolver para alert_state. Se o programa passar patrol_state, o Verse passará estruturalmente para o case padrão e executará expression5.
Como usar case com outro fluxo de controle
Os blocos na instrução case poderão ser interrompidos e continuar se a instrução de caso estiver em um loop. Blocos de instruções de caso também poderão retornar da função em que estão.
Por exemplo:
loop:
case (x):
42 => break
_ => {}Esse loop absurdo será encerrado imediatamente se x = 42 ou se repetir indefinidamente.
Outro exemplo:
Foo(x : int) : int =
case (x):
100 => return 200
_ => return 100Este exemplo é equivalente a:
Foo(x : int) : int =
case (x):
100 => 200
_ => 100O que acontece porque a instrução de caso é a última expressão da função.
Case padrão
Instruções case que não tiverem um case _=> (um case padrão) falharão se nenhum dos cases corresponder. Não há problema em usar essas instruções case em contextos de falha (como funções com o efeito decides).
As instruções case que corresponderem a todos os cases de uma enumeração não falharão mesmo se não tiverem um case _=>.