> For the complete documentation index, see [llms.txt](https://docs.allout.game/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.allout.game/all-out-docs/docs-es/programacion/types-and-structures.md).

# Conceptos básicos del lenguaje

Primitivas, enums, structs, clases, referencias y polimorfismo de CSL.

Esta página es la parte de “modelado de datos” de CSL: primitivos, structs/clases y los patrones que usarás para representar el estado del juego de forma limpia.

{% hint style="info" %}
Si eres nuevo, empieza con [Primeros pasos con CSL](/all-out-docs/docs-es/programacion/syntax.md). Esta página supone que ya sabes declarar variables y escribir `proc`/`method`.
{% endhint %}

## Tipos primitivos

### Números y booleanos

* Enteros con signo: `s8`, `s16`, `s32`, `s64` (alias: `int` == `s64`)
* Enteros sin signo: `u8`, `u16`, `u32`, `u64` (alias: `uint` == `u64`)
* Flotantes: `f32` (alias: `float`), `f64`
* Booleanos: `bool`

```go
health: int = 100;
speed: float = 6.5;
is_dead: bool = false;
opacity := .75; // igual que 0.75
```

CSL amplía los números cuando eso es seguro: los enteros con signo más pequeños pueden convertirse en enteros con signo más anchos, los enteros sin signo más pequeños pueden convertirse en enteros sin signo más anchos, los enteros sin signo pueden convertirse en enteros con signo más anchos cuando el destino puede contener todo el rango, y `f32` puede convertirse en `f64`.

### Cadenas

`string` se usa constantemente para IDs, nombres y formato.

```go
item_id := "sword";
log_info("picked up %", {item_id});

first_name := "Ada";
last_name := "Lovelace";
full_name := first_name + " " + last_name;
full_name += "!";
```

La concatenación funciona tanto en expresiones en tiempo de ejecución como en constantes en tiempo de compilación.

### Vectores

`v2`, `v3`, `v4` son tipos matemáticos/de datos integrados:

```go
pos: v2 = {10, 20};
color: v4 = {1, 0, 0, 1};
```

## Enumeraciones

Las enumeraciones son ideales para campos legibles de “modo/estado”:

```go
Game_Phase :: enum {
    LOBBY;
    RUNNING;
    POST_GAME;
}

phase := Game_Phase.LOBBY;

if phase == .RUNNING {
    // ...
}
```

{% hint style="info" %}
Los valores de los enums se suelen referenciar con la abreviatura `.VALUE` cuando el compilador puede inferir el tipo del enum.
{% endhint %}

## Structs (tipos por valor)

Usa structs para “datos simples” que quieras copiar de forma barata (configuración, pequeños bloques de estado, descriptores).

```go
Damage_Desc :: struct {
    amount: int;
    knockback: v2;
}

hit := Damage_Desc{amount=10, knockback={2, 1}};
```

Los structs pueden heredar de otros structs. Los literales compuestos incluyen primero los campos heredados:

```go
Base_Stats :: struct {
    health: int;
}

Enemy_Stats :: struct : Base_Stats {
    speed: float;
}

stats: Enemy_Stats = {100, 4.5};
```

### Cuándo usar un struct

* Un objeto descriptor/configuración (`*_Desc`)
* Estado pequeño e independiente que quieres copiar por valor
* Datos que quieres incrustar dentro de otro tipo

### Cuándo no usar un struct

* Estado mutable grande compartido entre varios sistemas (usa una clase)
* Objetos de “identidad” (jugadores, objetos, elementos de larga vida) (usa una clase)

## Clases (tipos de referencia)

Las clases son tipos de referencia. Crea instancias con `new(...)`.

```go
Enemy :: class {
    health: int = 50;
    target: v2 = {0, 0};
}

e := new(Enemy);
```

### Herencia

Puedes heredar de otros structs/clases:

```go
Weapon_Definition :: class {
    id: string;
    name: string;
}

Gun_Definition :: class : Weapon_Definition {
    fire_rate: float;
}
```

Las clases derivadas heredan los valores predeterminados de los campos. Pueden sobrescribir los valores predeterminados heredados con `field = value` en el cuerpo de la clase:

```go
Weapon_Definition :: class {
    damage: int = 10;
}

Rocket_Definition :: class : Weapon_Definition {
    damage = 100;
    splash_radius: float = 3.0;
}
```

Toda clase derivada tiene un `base` campo de solo lectura que ve el mismo objeto como su tipo padre inmediato. Úsalo cuando un método derivado sombrea un método padre con el mismo nombre y necesita seleccionar explícitamente el método padre:

```go
Weapon :: class {
    fire :: method() {
        // Comportamiento base.
    }
}

Burst_Weapon :: class : Weapon {
    fire :: method() {
        base.fire();
        // Comportamiento adicional de ráfaga.
    }
}
```

Los métodos de CSL no son virtuales. El tipo estático del receptor determina dónde comienza la búsqueda del método; un valor tipado como base nunca llama a un método con el mismo nombre declarado solo en su tipo derivado en tiempo de ejecución.

{% hint style="warning" %}
Usa herencia cuando exista una verdadera relación “es-un”. Para la mayoría de los datos de gameplay, la composición (campos) es más simple y fácil de mantener.
{% endhint %}

## Arrays, slices y arrays dinámicos

Verás tres formas comunes:

* **Arrays fijos**: `[N]T` (tamaño en tiempo de compilación)
* **Slices / arrays administrados**: `[]T` (una vista de un array)
* **Arrays dinámicos**: `[..]T` (lista redimensionable)

Ejemplo:

```go
spawn_points: [4]v2 = {{0,0}, {5,0}, {0,5}, {5,5}};

alive_enemy_ids: [..]int = {123, 456};
```

Para una guía completa, consulta [Arrays y colecciones](/all-out-docs/docs-es/programacion/arrays-and-collections.md).

## Pasar por referencia (`ref`)

Si un procedimiento necesita modificar un valor, usa `ref`:

```go
apply_damage :: proc(health: ref int, amount: int) {
    health -= amount;
}

hp := 100;
apply_damage(ref hp, 10);
```

Esto es especialmente útil para APIs de estilo de “distribución” que recortan/reducen progresivamente un rectángulo:

```go
draw_panel :: proc(rect: ref Rect) {
    header := rect.cut_top(50);
    draw_header(header);
    // rect ahora es el área restante para el contenido
}
```

## Conversión

Usa `expr.(T)` o `cast(T)expr`:

```go
f := 12.7;
i := f.(int);       // 12
f2 := cast(float)i; // 12.0
```

Cuando el tipo de destino ya se conoce, `expr.()` y `cast expr` infiere el tipo de destino.

## Polimorfismo de tipos (procedimientos de estilo genérico)

CSL admite procedimientos polimórficos usando `$` para deducir tipos en el sitio de llamada:

```go
min :: proc(a: $T, b: T) -> T {
    if a < b return a;
    return b;
}

a := min(10, 20);       // T == int
b := min(1.25, 3.5);    // T == float
```

## Tipos como valores (`typeid`)

`typeid` es un valor que representa un tipo en tiempo de ejecución y/o para llamadas polimórficas:

```go
default_of :: proc($T: typeid) -> T {
    t: T;
    return t;
}

zero := default_of(int);
empty := default_of(string);
```

Los casts entre clases solo son válidos entre tipos relacionados. Los casts de derivado a base son gratuitos; los casts de base a derivado validan el tipo concreto del objeto en tiempo de ejecución y generan un error si no es el tipo solicitado o una de sus subclases. Convertir un valor de clase nulo produce nulo. Usa `value.#type` cuando selecciones comportamiento entre varios tipos derivados posibles en lugar de usar un cast fallido como prueba de tipo.

## Pautas prácticas de modelado

* **El estado por jugador vive en `Player`.** Si debe diferir entre jugadores, no debería ser global.
* **Prefiere structs pequeños para descriptores** y almacena el estado en tiempo de ejecución en clases/componentes.
* **Ejecuta el gameplay en la ruta predicha compartida.** No calcules el estado del gameplay solo bajo `is_local()` o protégelo con `Game.is_server()`.

Para patrones específicos por jugador, consulta [Añadir lógica de jugador](/all-out-docs/docs-es/programacion/player-model.md). Para la parte ECS del mundo, consulta [Entidades y componentes](/all-out-docs/docs-es/programacion/entities-and-components.md).
